ukui-panel-3.0.6.4/0000755000175000017500000000000014204636772012367 5ustar fengfengukui-panel-3.0.6.4/plugin-tray/0000755000175000017500000000000014204636772014642 5ustar fengfengukui-panel-3.0.6.4/plugin-tray/ukuitraystrage.cpp0000644000175000017500000002202214204636772020427 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include #include "ukuitray.h" #include "xfitman.h" #include #include #include #include #include #include #include #include "ukuitrayplugin.h" #undef Bool // defined as int in X11/Xlib.h #include "../panel/iukuipanelplugin.h" #include "../panel/common_fun/listengsettings.h" #include #include #include #include #include storageBarStatus status; /*收纳栏*/ UKUIStorageFrame::UKUIStorageFrame(QWidget *parent): QWidget(parent, Qt::Popup) { installEventFilter(this); setLayout(new UKUi::GridLayout(this)); dynamic_cast(layout())->setRowCount(1); dynamic_cast(layout())->setColumnCount(1); setMinimumHeight(0); setMinimumWidth(0); setAttribute(Qt::WA_TranslucentBackground);//设置窗口背景透明 /* * @brief setWindowFlags * * 冲突的窗口属性 这里本应使用Popup窗口属性,但是popup的属性与托盘有冲突 * 会使得点击事件无法生效 * * 备选方案是使用QToolTip 这导致了无法进入事件过滤来检测活动窗口的变化 * * Qt::WindowStaysOnTopHint | Qt::Tool | Qt::FramelessWindowHint * 这三个参数分别代表 设置窗体一直置顶,并且不会抢焦点 | 工具窗口 |设置窗体无边框,不可拖动拖拽拉伸 * * 但是在某些情况下会出现在任务啦上依然会显示窗口,因此加入新的属性 X11BypassWindowManagerHint * Qt::WindowDoesNotAcceptFocus:不接受焦点 */ setWindowFlags(Qt::WindowStaysOnTopHint | Qt::Tool | Qt::FramelessWindowHint| Qt::X11BypassWindowManagerHint /*| Qt::WindowDoesNotAcceptFocus*/); // setWindowFlags(Qt::Popup/*| Qt::WindowDoesNotAcceptFocus*/); _NET_SYSTEM_TRAY_OPCODE = XfitMan::atom("_NET_SYSTEM_TRAY_OPCODE"); ListenGsettings *m_ListenGsettings = new ListenGsettings(); QObject::connect(m_ListenGsettings,&ListenGsettings::iconsizechanged,[this](int size){iconsize=size;}); QObject::connect(m_ListenGsettings,&ListenGsettings::panelpositionchanged,[this](int size){panelPosition=size;}); QObject::connect(m_ListenGsettings,&ListenGsettings::panelsizechanged,[this](int size){panelsize=size;}); QDBusConnection::sessionBus().connect(QString(), QString("/panel"), "org.ukui.panel.settings", "PanelHided", this, SLOT(hideStorageFrame(void))); } UKUIStorageFrame::~UKUIStorageFrame(){ } /* * 事件过滤,检测鼠标点击外部活动区域则收回收纳栏 */ bool UKUIStorageFrame::eventFilter(QObject *obj, QEvent *event) { // Q_UNUSED(obj); // Q_UNUSED(event); if (obj == this) { /*   //绑定快捷键 if (event->type() == QEvent::KeyPress) { //将QEvent对象转换为真正的QKeyEvent对象 QKeyEvent *keyEvent = static_cast(event); if (keyEvent->key() == Qt::Key_Tab) { this->hide(); status=ST_HIDE; return true; } } */ /* 这里处理的鼠标左键和右键事件只是TrayIcon 区域,图标之外的部分 * 与在trayIcon类中处理mousePressEvent是一样的      */ if (event->type() == QEvent::MouseButtonPress) { //将QEvent对象转换为真正的QKeyEvent对象 QMouseEvent *mouseEvent = static_cast(event); if (mouseEvent->button() == Qt::LeftButton) { this->hide(); status=ST_HIDE; return true; } else if(mouseEvent->button() == Qt::RightButton) { return true; } } else if(event->type() == QEvent::ContextMenu) { return false; } else if (event->type() == QEvent::WindowDeactivate &&status==ST_SHOW) { // qDebug()<<"激活外部窗口"; this->hide(); status=ST_HIDE; return true; } else if (event->type() == QEvent::StyleChange) { } } if (!isActiveWindow()) { activateWindow(); } return false; } void UKUIStorageFrame::paintEvent(QPaintEvent *event) { QStyleOption opt; opt.init(this); QPainter p(this); p.setBrush(QBrush(QColor(0x13,0x14,0x14,0x4d))); p.setPen(Qt::NoPen); p.setRenderHint(QPainter::Antialiasing); // 反锯齿; QPainterPath path; p.drawRoundedRect(opt.rect,6,6); path.addRoundedRect(opt.rect,6,6); setProperty("blurRegion",QRegion(path.toFillPolygon().toPolygon())); style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); } void UKUIStorageFrame::setStorageFramGeometry() { // int totalHeight = qApp->primaryScreen()->size().height() + qApp->primaryScreen()->geometry().y(); // int totalWidth = qApp->primaryScreen()->size().width() + qApp->primaryScreen()->geometry().x(); // switch (panel()->position()) { // case IUKUIPanel::PositionBottom: // this->setGeometry(totalWidth-mViewWidht-4,totalHeight-panel()->panelSize()-mViewHeight-4,mViewWidht,mViewHeight); // break; // case IUKUIPanel::PositionTop: // mWebViewDiag->setGeometry(totalWidth-mViewWidht-4,qApp->primaryScreen()->geometry().y()+panel()->panelSize()+4,mViewWidht,mViewHeight); // break; // case IUKUIPanel::PositionLeft: // mWebViewDiag->setGeometry(qApp->primaryScreen()->geometry().x()+panel()->panelSize()+4,totalHeight-mViewHeight-4,mViewWidht,mViewHeight); // break; // case IUKUIPanel::PositionRight: // mWebViewDiag->setGeometry(totalWidth-panel()->panelSize()-mViewWidht-4,totalHeight-mViewHeight-4,mViewWidht,mViewHeight); // break; // default: // mWebViewDiag->setGeometry(qApp->primaryScreen()->geometry().x()+panel()->panelSize()+4,totalHeight-mViewHeight,mViewWidht,mViewHeight); // break; // } } #define mWinWidth 46 #define mWinHeight 46 void UKUIStorageFrame::setStorageFrameSize(int size) { int winWidth = 0; int winHeight = 0; this->setLayout(new UKUi::GridLayout); switch(size) { case 1: winWidth = mWinWidth; winHeight = mWinHeight; break; case 2: winWidth = mWinWidth*2; winHeight = mWinHeight; break; case 3: winWidth = mWinWidth*3; winHeight = mWinHeight; break; case 4 ... 6: winWidth = mWinWidth*3; winHeight = mWinHeight*2; break; case 7 ... 9: winWidth = mWinWidth*3; winHeight = mWinHeight*3; break; case 10 ... 12: winWidth = mWinWidth*3; winHeight = mWinHeight*4; break; case 13 ... 40: //默认情况下的布局 winWidth = mWinWidth*4; winHeight = mWinHeight*4; break; default: winWidth = 0; winHeight = 0; break; } this->setFixedSize(winWidth,winHeight); // int totalHeight = qApp->primaryScreen()->size().height() + qApp->primaryScreen()->geometry().y(); // int totalWidth = qApp->primaryScreen()->size().width() + qApp->primaryScreen()->geometry().x(); // switch (panelPosition) { // case 0: // this->setGeometry(totalWidth-this->cursor().pos().x()-winWidth/2-4,totalHeight-panelsize-winHeight-4,winWidth,winHeight); // break; // case 1: // this->setGeometry(totalWidth-winWidth-4,qApp->primaryScreen()->geometry().y()+panelsize+4,winWidth,winHeight); // break; // case 2: // this->setGeometry(qApp->primaryScreen()->geometry().x()+panelsize+4,totalHeight-winHeight-4,winWidth,winHeight); // break; // case 3: // this->setGeometry(totalWidth-panelsize-winWidth-4,totalHeight-winHeight-4,winWidth,winHeight); // break; // default: // this->setGeometry(qApp->primaryScreen()->geometry().x()+panelsize+4,totalHeight-winHeight,winWidth,winHeight); // break; // } } void UKUIStorageFrame::hideStorageFrame() { qDebug()<<"UKUIStorageFrame::hideStorageFrame"; this->hide(); } ukui-panel-3.0.6.4/plugin-tray/ukuitray.h0000644000175000017500000001502414204636772016672 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include #include #include "fixx11h.h" #include #include #include #include #include #include #include #include "../panel/iukuipanel.h" #include "../panel/customstyle.h" #include "../panel/ukuicontrolstyle.h" #include "ukuitraystrage.h" #include "storagearrow.h" #include "ukuistoragewidget.h" class TrayIcon; class QSize; namespace UKUi { class GridLayout; } /** * @brief This makes our trayplugin */ class UKUITrayPlugin; class UKUITray: public QFrame, QAbstractNativeEventFilter { Q_OBJECT // Q_PROPERTY(QSize iconSize READ iconSize WRITE setIconSize) public: /** * @brief UKUITray * @param plugin * @param parent * 托盘应用共分为两个区域 Tray Storage * Tray区域 :UKUITray ; Storage区域:UKUIStorageFrame * 图标可存放在两个区域中的任何一个区域,如果应用退出则被销毁 */ UKUITray(UKUITrayPlugin *plugin, QWidget* parent = 0); ~UKUITray(); QSize iconSize() const { return mIconSize; } /** * @brief setIconSize * 目前托盘应用不使用此方式设置控件的大小而是使用setIconSize和setFixedSize来设置 */ void setIconSize(); /** @brief nativeEventFilter * 托盘应用的事件过滤器 * 通过继承QAbstractNativeEventFilter的类中重新实现nativeEventFilter接口: * 安装 : void QCoreApplication::installNativeEventFilter(QAbstractNativeEventFilter *filterObj) * 或者   void QAbstractEventDispatcher::installNativeEventFilter(QAbstractNativeEventFilter *filterObj) * XCB(Linux) 对应的eventType 类型如下: * 事件类型(eventType):“xcb_generic_event_t”   消息类型(message):xcb_generic_event_t *  结果类型(result):无 */ bool nativeEventFilter(const QByteArray &eventType, void *message, long *); UKUITrayPlugin *mPlugin; /** * @brief regulateIcon * @param mid * 调节图标,监听图标所在的位置 */ void regulateIcon(Window *mid); /** * @brief newAppDetect * @param wid 应用的窗口id * 检测到新的应用(第一次添加应用) */ void newAppDetect(int wid); QStringList getShowInTrayApp(); /** * @brief showAndHideStorage * 在取消了panel的WindowDoesNotAcceptFocus属性之后,托盘栏会有点击之后的隐藏并再次弹出的操作 */ void showAndHideStorage(bool); protected: void contextMenuEvent(QContextMenuEvent *event); public slots: /** * @brief storageBar * 点击收纳按钮的时候的槽函数 */ void storageBar(); void hideStorageWidget(); /** * @brief realign * 关于设置托盘栏图标大小的方法 * ukui采用与lxqt-panel不同的方式 * 直接在realign函数中进行设置每个托盘应用所在的位置的大小和位置 */ void realign(); signals: void iconSizeChanged(int iconSize); void freezeIcon(TrayIcon *icon,Window winid); void positionChanged(); private slots: /** * @brief startTray * freedesktop systray specification * 托盘规范 */ void startTray(); void stopTray(); // void stopStorageTray(); /** * @brief onIconDestroyed * @param icon * 将托盘图标从托盘栏/收纳栏中移除 */ void onIconDestroyed(QObject * icon); void trayIconSizeRefresh(); /** * @brief switchButtons * @param button1 移动前的图标 * @param button2 移动后的图标 * 交换两个图标 */ void switchButtons(TrayIcon *button1, TrayIcon *button2); private: VisualID getVisual(); void clientMessageEvent(xcb_generic_event_t *e); int clientMessage(WId _wid, Atom _msg, long unsigned int data0, long unsigned int data1 = 0, long unsigned int data2 = 0, long unsigned int data3 = 0, long unsigned int data4 = 0) const; /** * @brief addTrayIcon * @param id * 添加托盘应用到托盘栏 */ void addTrayIcon(Window id); void addStorageIcon(Window winId); void moveIconToStorage(Window id); void moveIconToTray(Window winId); /** * @brief handleStorageUi * 收纳栏样式 * 根据panel的大小自动调节收纳栏 * 未设置m_pwidget的透明属性会导致收纳栏异常(布局混乱) * 因此不使用QWidget,而是继承 QWidget 写一个 UKUiStorageWidget,并设置其基础样式 */ void handleStorageUi(); TrayIcon* findIcon(Window trayId); TrayIcon* findTrayIcon(Window trayId); TrayIcon* findStorageIcon(Window trayId); bool mValid; Window mTrayId; QList mIcons; QList mTrayIcons; QList mStorageIcons; int mDamageEvent; int mDamageError; QSize mIconSize; /** * @brief mLayout * 托盘上的图标布局 */ UKUi::GridLayout *mLayout; /** * @brief mStorageLayout * 收纳栏上布局 */ UKUi::GridLayout *mStorageLayout; /** * @brief mStorageItemLayout * 收纳栏上的图标布局 */ UKUi::GridLayout *mStorageItemLayout; Atom _NET_SYSTEM_TRAY_OPCODE; Display* mDisplay; UKUIStorageFrame *storageFrame; UKUiStorageWidget *m_pwidget; StorageArrow *mBtn; QPixmap drawSymbolicColoredPixmap(const QPixmap &source); QGSettings *settings; //针对ukui桌面环境应用的特殊处理 bool fcitx_flag = false; /** * @brief panelStartupFcitx * 任务栏拉起fcitx */ void panelStartupFcitx(); }; #endif ukui-panel-3.0.6.4/plugin-tray/trayicon.cpp0000644000175000017500000006366214204636772017213 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include #include #include #include #include #include "../panel/ukuipanel.h" #include "trayicon.h" #include "xfitman.h" #include #include #include #include #include #include "qmath.h" #include #define XEMBED_EMBEDDED_NOTIFY 0 //适配高分屏 #include #include #include #include #define FONT_RENDERING_DPI "org.ukui.SettingsDaemon.plugins.xsettings" #define SCALE_KEY "scaling-factor" static bool xError; #define MIMETYPE "ukui/UkuiTray" #define CSETTINGS_SCALING "org.ukui.SettingsDaemon.plugins.xsettings" #define SCALING_FACTOR "scalingFactor" #define ORG_UKUI_STYLE "org.ukui.style" #define STYLE_NAME "styleName" #define STYLE_NAME_KEY_DARK "ukui-dark" #define STYLE_NAME_KEY_DEFAULT "ukui-default" #define STYLE_NAME_KEY_UKUI "ukui" #define STYLE_NAME_KEY_BLACK "ukui-black" #define STYLE_NAME_KEY_LIGHT "ukui-light" #define STYLE_NAME_KEY_WHITE "ukui-white" int windowErrorHandler(Display *d, XErrorEvent *e) { xError = true; if (e->error_code != BadWindow) { char str[1024]; XGetErrorText(d, e->error_code, str, 1024); qWarning() << "Error handler" << e->error_code << str; } return 0; } /************************************************ ************************************************/ TrayIcon::TrayIcon(Window iconId, QSize const & iconSize, QWidget* parent): QToolButton(parent), mIconId(iconId), mWindowId(0), mIconSize(iconSize), mDamage(0), mDisplay(QX11Info::display()) { /* * NOTE: * 如果不保存QX11Info::display()的返回值,ukui-panel会有潜在崩溃问题 * it's a good idea to save the return value of QX11Info::display(). * In Qt 5, this API is slower and has some limitations which can trigger crashes. * The XDisplay value is actally stored in QScreen object of the primary screen rather than * in a global variable. So when the parimary QScreen is being deleted and becomes invalid, * QX11Info::display() will fail and cause crash. Storing this value improves the efficiency and * also prevent potential crashes caused by this bug. */ traystatus=NORMAL; setObjectName("TrayIcon"); setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); setAcceptDrops(false); QTimer::singleShot(200, [this] { init(); update(); }); repaint(); /**/ QDBusConnection::sessionBus().unregisterService("com.ukui.panel"); QDBusConnection::sessionBus().registerService("com.ukui.panel"); QDBusConnection::sessionBus().registerObject("/traybutton/click", this,QDBusConnection :: ExportAllSlots | QDBusConnection :: ExportAllSignals); const QByteArray scaling_factor(CSETTINGS_SCALING); if(QGSettings::isSchemaInstalled(scaling_factor)) { scaling_settings = new QGSettings(scaling_factor); qDebug()<<"scaling_settings->get(SCALING_FACTOR).toInt()"<get(SCALING_FACTOR).toInt(); } const QByteArray id(ORG_UKUI_STYLE); QStringList stylelist; stylelist<get(STYLE_NAME).toString())) dark_style=true; else dark_style=false; } connect(gsettings, &QGSettings::changed, this, [=] (const QString &key){ if(key==STYLE_NAME){ if(stylelist.contains(gsettings->get(STYLE_NAME).toString())) dark_style=true; else dark_style=false; repaint(); } }); const QByteArray System_Palette_id(FONT_RENDERING_DPI); if(QGSettings::isSchemaInstalled(System_Palette_id)){ //this->update(); System_scale_gsettings = new QGSettings(System_Palette_id); scale = System_scale_gsettings->get(SCALE_KEY).toFloat(); qDebug()<<"scale is "<get(SCALE_KEY).toFloat(); qDebug()<<"scale is "<update(); } }); } } /************************************************ ************************************************/ void TrayIcon::init() { Display* dsp = mDisplay; XWindowAttributes attr; if (! XGetWindowAttributes(dsp, mIconId, &attr)) { deleteLater(); return; } // qDebug() << "New tray icon ***********************************"; // qDebug() << " * window id: " << hex << mIconId; qDebug() << "Plugin-Tray Get Tray App Name :: " << xfitMan().getApplicationName(mIconId); // qDebug() << " * size (WxH): " << attr.width << "x" << attr.height; // qDebug() << " * color depth:" << attr.depth; unsigned long mask = 0; XSetWindowAttributes set_attr; Visual* visual = attr.visual; set_attr.colormap = attr.colormap; set_attr.background_pixel = 0; set_attr.border_pixel = 0; mask = CWColormap|CWBackPixel|CWBorderPixel; const QRect icon_geom = iconGeometry(); mWindowId = XCreateWindow(dsp, this->winId(), icon_geom.x(), icon_geom.y(), icon_geom.width() * metric(PdmDevicePixelRatio), icon_geom.height() * metric(PdmDevicePixelRatio), 0, attr.depth, InputOutput, visual, mask, &set_attr); xError = false; XErrorHandler old; old = XSetErrorHandler(windowErrorHandler); XReparentWindow(dsp, mIconId, mWindowId, 0, 0); XSync(dsp, false); XSetErrorHandler(old); if (xError) { qWarning() << "* Not icon_swallow *"; XDestroyWindow(dsp, mWindowId); mWindowId = 0; deleteLater(); return; } { Atom acttype; int actfmt; unsigned long nbitem, bytes; unsigned char *data = 0; int ret; ret = XGetWindowProperty(dsp, mIconId, xfitMan().atom("_XEMBED_INFO"), 0, 2, false, xfitMan().atom("_XEMBED_INFO"), &acttype, &actfmt, &nbitem, &bytes, &data); if (ret == Success) { if (data) XFree(data); } else { qWarning() << "TrayIcon: xembed error"; XDestroyWindow(dsp, mWindowId); deleteLater(); return; } } { XEvent e; e.xclient.type = ClientMessage; e.xclient.serial = 0; e.xclient.send_event = True; e.xclient.message_type = xfitMan().atom("_XEMBED"); e.xclient.window = mIconId; e.xclient.format = 32; e.xclient.data.l[0] = CurrentTime; e.xclient.data.l[1] = XEMBED_EMBEDDED_NOTIFY; e.xclient.data.l[2] = 0; e.xclient.data.l[3] = mWindowId; e.xclient.data.l[4] = 0; XSendEvent(dsp, mIconId, false, 0xFFFFFF, &e); } XSelectInput(dsp, mIconId, StructureNotifyMask); mDamage = XDamageCreate(dsp, mIconId, XDamageReportRawRectangles); XCompositeRedirectWindow(dsp, mWindowId, CompositeRedirectManual); XMapWindow(dsp, mIconId); XMapRaised(dsp, mWindowId); const QSize req_size{mIconSize * metric(PdmDevicePixelRatio)}; XResizeWindow(dsp, mIconId, req_size.width(), req_size.height()); } /************************************************ ************************************************/ TrayIcon::~TrayIcon() { Display* dsp = mDisplay; XSelectInput(dsp, mIconId, NoEventMask); if (mDamage) XDamageDestroy(dsp, mDamage); // reparent to root xError = false; XErrorHandler old = XSetErrorHandler(windowErrorHandler); XUnmapWindow(dsp, mIconId); XReparentWindow(dsp, mIconId, QX11Info::appRootWindow(), 0, 0); if (mWindowId) XDestroyWindow(dsp, mWindowId); XSync(dsp, False); XSetErrorHandler(old); } /************************************************ ************************************************/ QSize TrayIcon::sizeHint() const { QMargins margins = contentsMargins(); return QSize(margins.left() + mIconSize.width() + margins.right(), margins.top() + mIconSize.height() + margins.bottom() ); } /************************************************ ************************************************/ void TrayIcon::setIconSize(QSize iconSize) { mIconSize = iconSize; const QSize req_size{mIconSize * metric(PdmDevicePixelRatio)}; if (mWindowId) xfitMan().resizeWindow(mWindowId, req_size.width(), req_size.height()); if (mIconId) xfitMan().resizeWindow(mIconId, req_size.width(), req_size.height()); } /*处理 TrayIcon 绘图,点击等事件*/ bool TrayIcon::event(QEvent *event) { if (mWindowId) { switch (event->type()) { case QEvent::Paint: /*必须在draw函数中绘制图标,若在paintEvent中绘制则XGetImage 会出错*/ draw(static_cast(event)); break; case QEvent::Move: case QEvent::Resize: { QRect rect = iconGeometry(); xfitMan().moveWindow(mWindowId, rect.left(), rect.top()); } break; case QEvent::MouseButtonPress: // trayButtonPress(static_cast(event)); // break; //trayButtonCoordinateMapping(x_panel,y_panel); // break; case QEvent::MouseButtonRelease: case QEvent::MouseButtonDblClick: event->accept(); break; case QEvent::ContextMenu: // moveMenu(); break; case QEvent::Enter: // this->setToolTip("右键可选择移入任务栏/收纳"); break; default: break; } } return QToolButton::event(event); } /************************************************ ************************************************/ QRect TrayIcon::iconGeometry() { QRect res = QRect(QPoint(0, 0), mIconSize); res.moveCenter(QRect(0, 0, width(), height()).center()); return res; } /** * @brief needReDraw 判断图标是否需要重新绘制(高亮处理) * @return 不需要重新绘制的图标返回值为false * 备注:ukui3.1 主题提供两套图标后,任务栏不需要进行重新绘制 */ bool TrayIcon::needReDraw() { QStringList ignoreAppList; ignoreAppList<<"kylin-video"; if(ignoreAppList.contains(xfitMan().getApplicationName(mIconId))){ return false; } return true; } /*draw 函数执行的是绘图事件*/ void TrayIcon::draw(QPaintEvent* /*event*/) { Display* dsp = mDisplay; XWindowAttributes attr; if (!XGetWindowAttributes(dsp, mIconId, &attr)) { qWarning() << "Paint error"; return; } QImage image; XImage* ximage = XGetImage(dsp, mIconId, 0, 0, attr.width, attr.height, AllPlanes, ZPixmap); if(ximage) { image = QImage((const uchar*) ximage->data, ximage->width, ximage->height, ximage->bytes_per_line, QImage::Format_ARGB32_Premultiplied); } else { qWarning() << " * Error image is NULL"; XClearArea(mDisplay, (Window)winId(), 0, 0, attr.width, attr.height, False); // for some unknown reason, XGetImage failed. try another less efficient method. // QScreen::grabWindow uses XCopyArea() internally. image = qApp->primaryScreen()->grabWindow(mIconId).toImage(); } // qDebug() << "Paint icon **************************************"; // qDebug() << " * XComposite: " << isXCompositeAvailable(); // qDebug() << " * Icon geometry:" << iconGeometry(); // qDebug() << " Icon"; // qDebug() << " * window id: " << hex << mIconId; // qDebug() << " * window name:" << xfitMan().getName(mIconId); // qDebug() << " * size (WxH): " << attr.width << "x" << attr.height; // qDebug() << " * pos (XxY): " << attr.x << attr.y; // qDebug() << " * color depth:" << attr.depth; // qDebug() << " XImage"; // qDebug() << " * size (WxH): " << ximage->width << "x" << ximage->height; // switch (ximage->format) // { // case XYBitmap: qDebug() << " * format: XYBitmap"; break; // case XYPixmap: qDebug() << " * format: XYPixmap"; break; // case ZPixmap: qDebug() << " * format: ZPixmap"; break; // } // qDebug() << " * color depth: " << ximage->depth; // qDebug() << " * bits per pixel:" << ximage->bits_per_pixel; QPainter painter(this); QRect iconRect = iconGeometry(); if (image.size() != iconRect.size()) { image = image.scaled(iconRect.size(), Qt::KeepAspectRatio, Qt::SmoothTransformation); QRect r = image.rect(); r.moveCenter(iconRect.center()); iconRect = r; } if(needReDraw()) // image=HighLightEffect::drawSymbolicColoredPixmap(QPixmap::fromImage(image)).toImage(); image = drawSymbolicColoredPixmap(QPixmap::fromImage(image)).toImage(); painter.setRenderHints(QPainter::SmoothPixmapTransform); painter.setRenderHints(QPainter::Antialiasing, true); painter.drawImage(iconRect, image); if(ximage) XDestroyImage(ximage); } /*关于点击托盘应用的非图标区域实现打开托盘应用*/ void TrayIcon::trayButtonPress(QMouseEvent* /*event*/) { //qDebug() << " * window name:" << xfitMan().getApplicationName(mIconId); /* 需要此点击信号的应用需要做如下绑定 * QDBusConnection::sessionBus().connect(QString(), QString("/traybutton/click"), "com.ukui.panel.plugins.tray", "ClickTrayApp", this, SLOT(clientGet(void))); * 在槽函数clientGet(void) 中处理接受到的点击信号 */ QDBusMessage message =QDBusMessage::createSignal("/traybutton/click", "com.ukui.panel.plugins.tray", "ClickTrayApp"); message<width()/2&&y_clickheight()/2){ x=x_desktop.x()+qAbs(x_click-mid_icon_click_w); y=x_desktop.y()-qAbs(y_click-mid_icon_click_h); }else if (x_click>width()/2&&y_click>=height()/2){ x=x_desktop.x()-qAbs(x_click-mid_icon_click_w); y=x_desktop.y()-qAbs(y_click-mid_icon_click_h); }else{ qDebug()<<"no change click position"; } qDebug()<<"position right_down x "<width()/2&&y_clickheight()/2){ x=x_desktop.x()*2+qAbs(x_click*2-mid_icon_click_w); y=x_desktop.y()*2-qAbs(y_click*2-mid_icon_click_h); }else if (x_click>width()/2&&y_click>=height()/2){ x=x_desktop.x()*2-qAbs(x_click*2-mid_icon_click_w); y=x_desktop.y()*2-qAbs(y_click*2-mid_icon_click_h); }else{ qDebug()<<"no change click position"; } qDebug()<<"position right_down x "<width()/2&&y_clickheight()/2){ x=x_desktop.x()*scale+qAbs(x_click*scale-mid_icon_click_w); y=x_desktop.y()*scale-qAbs(y_click*scale-mid_icon_click_h); }else if (x_click>width()/2&&y_click>=height()/2){ x=x_desktop.x()*scale-qAbs(x_click*scale-mid_icon_click_w); y=x_desktop.y()*scale-qAbs(y_click*scale-mid_icon_click_h); }else{ qDebug()<<"no change click position"; } qDebug()<<"position right_down x "<drawPrimitive(QStyle::PE_Widget, &opt, &p, this); } QPixmap TrayIcon::drawSymbolicColoredPixmap(const QPixmap &source) { QColor standard (31,32,34); QImage img = source.toImage(); for (int x = 0; x < img.width(); x++) { for (int y = 0; y < img.height(); y++) { auto color = img.pixelColor(x, y); if (color.alpha() > 0) { if(dark_style && qAbs(color.red()-standard.red())<20 && qAbs(color.green()-standard.green())<20 && qAbs(color.blue()-standard.blue())<20){ color.setRed(255); color.setGreen(255); color.setBlue(255); // color.setRgb(255,255,255); img.setPixelColor(x, y, color); } else{ img.setPixelColor(x, y, color); } } } } return QPixmap::fromImage(img); } void TrayIcon::moveMenu() { menu =new QMenu(this); menu->setAttribute(Qt::WA_DeleteOnClose); QAction *action; action = menu->addAction(tr("移入任务栏/收纳")); connect(action, &QAction::triggered, [this] { emit iconIsMoving(mIconId);}); menu->setGeometry(caculateMenuWindowPos(QCursor::pos(), menu->sizeHint())); menu->show(); } void TrayIcon::notifyAppFreeze() { emit notifyTray(mIconId); } void TrayIcon::emitIconId() { emit iconIsMoving(mIconId); } QRect TrayIcon::caculateMenuWindowPos(const QPoint &absolutePos, const QSize &windowSize) { int x = absolutePos.x(), y = absolutePos.y(); QRect res(QPoint(x, y), windowSize); QRect screen = QApplication::desktop()->screenGeometry(this); // NOTE: We cannot use AvailableGeometry() which returns the work area here because when in a // multihead setup with different resolutions. In this case, the size of the work area is limited // by the smallest monitor and may be much smaller than the current screen and we will place the // menu at the wrong place. This is very bad for UX. So let's use the full size of the screen. if (res.right() > screen.right()) res.moveRight(screen.right()); if (res.bottom() > screen.bottom()) res.moveBottom(screen.bottom()); if (res.left() < screen.left()) res.moveLeft(screen.left()); if (res.top() < screen.top()) res.moveTop(screen.top()); return res; } #if 1 void TrayIcon::mouseMoveEvent(QMouseEvent *e) { if (e->button() == Qt::RightButton) return; if (!(e->buttons() & Qt::LeftButton)) return; if ((e->pos() - mDragStart).manhattanLength() < QApplication::startDragDistance()) return; if (e->modifiers() == Qt::ControlModifier) { return; } QDrag *drag = new QDrag(this); QIcon ico = icon(); int size = 16; QPixmap img = ico.pixmap(ico.actualSize({size, size})); drag->setMimeData(mimeData()); drag->setPixmap(img); drag->setHotSpot(img.rect().bottomRight()); drag->exec(); drag->deleteLater(); QAbstractButton::mouseMoveEvent(e); } void TrayIcon::dragMoveEvent(QDragMoveEvent * e) { emit iconIsMoving(mIconId); if (e->mimeData()->hasFormat(MIMETYPE)) e->acceptProposedAction(); else e->ignore(); } void TrayIcon::dragEnterEvent(QDragEnterEvent *e) { e->acceptProposedAction(); const TrayButtonMimeData *mimeData = qobject_cast(e->mimeData()); if (mimeData && mimeData->button()) emit switchButtons(mimeData->button(), this); QToolButton::dragEnterEvent(e); } QMimeData * TrayIcon::mimeData() { TrayButtonMimeData *mimeData = new TrayButtonMimeData(); // QByteArray ba; // mimeData->setData(mimeDataFormat(), ba); mimeData->setButton(this); return mimeData; } void TrayIcon::mousePressEvent(QMouseEvent *e) { if (e->button() == Qt::LeftButton && e->modifiers() == Qt::ControlModifier) { mDragStart = e->pos(); return; } QPoint panel_click= e->pos(); x_panel=panel_click.x(); y_panel=panel_click.y(); trayButtonCoordinateMapping(x_panel,y_panel); QToolButton::mousePressEvent(e); } #endif ukui-panel-3.0.6.4/plugin-tray/storagearrow.h0000644000175000017500000000261514204636772017536 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include enum storageArrowStatus{NORMAL,HOVER,PRESS}; class StorageArrow : public QPushButton { public : StorageArrow(QWidget* parent ); ~StorageArrow(); protected : // void paintEvent(QEvent *); /** * @brief enterEvent leaveEvent * @param event * enterEvent leaveEvent 只是为了解决鼠标离开按钮后依然出现的悬浮现象 */ void enterEvent(QEvent *event); void leaveEvent(QEvent *event); private: void setArrowIcon(); int GetTaskbarInfo(); QGSettings *gsetting; int panelPosition; int iconsize; }; #endif ukui-panel-3.0.6.4/plugin-tray/traydynamicgsetting.cpp0000644000175000017500000001026114204636772021437 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include } #define MAX_CUSTOM_SHORTCUTS 100 #define KEYBINDINGS_CUSTOM_SCHEMA "org.ukui.panel.tray" #define KEYBINDINGS_CUSTOM_DIR "/org/ukui/tray/keybindings/" #define ACTION_KEY "action" #define RECORD_KEY "record" #define BINDING_KEY "binding" #define NAME_KEY "name" QString findFreePath(){ int i = 0; char * dir; bool found; QList existsdirs; existsdirs = listExistsPath(); for (; i < MAX_CUSTOM_SHORTCUTS; i++){ found = true; dir = QString("custom%1/").arg(i).toLatin1().data(); for (int j = 0; j < existsdirs.count(); j++) if (!g_strcmp0(dir, existsdirs.at(j))){ found = false; break; } if (found) break; } if (i == MAX_CUSTOM_SHORTCUTS){ qDebug() << "Keyboard Shortcuts" << "Too many custom shortcuts"; return ""; } return QString("%1%2").arg(KEYBINDINGS_CUSTOM_DIR).arg(QString(dir)); } QList listExistsPath(){ char ** childs; int len; DConfClient * client = dconf_client_new(); childs = dconf_client_list (client, KEYBINDINGS_CUSTOM_DIR, &len); g_object_unref (client); QList vals; for (int i = 0; childs[i] != NULL; i++){ if (dconf_is_rel_dir (childs[i], NULL)){ gchar *val = g_strdup (childs[i]); vals.append(val); } } g_strfreev (childs); return vals; } void freezeApp() { QList existsPath = listExistsPath(); for (char * path : existsPath){ QString p =KEYBINDINGS_CUSTOM_DIR; std::string str = p.toStdString(); const int len = str.length(); char * prepath = new char[len+1]; strcpy(prepath,str.c_str()); char * allpath = strcat(prepath, path); const QByteArray ba(KEYBINDINGS_CUSTOM_SCHEMA); const QByteArray bba(allpath); QGSettings *settings; const QByteArray id(KEYBINDINGS_CUSTOM_SCHEMA); if(QGSettings::isSchemaInstalled(id)) { settings= new QGSettings(ba, bba); settings->set(ACTION_KEY,"freeze"); } } } void freezeTrayApp(int winId) { QList existsPath = listExistsPath(); int bingdingStr; for (char * path : existsPath) { QString p =KEYBINDINGS_CUSTOM_DIR; std::string str = p.toStdString(); const int len = str.length(); char * prepath = new char[len+1]; strcpy(prepath,str.c_str()); char * allpath = strcat(prepath, path); const QByteArray ba(KEYBINDINGS_CUSTOM_SCHEMA); const QByteArray bba(allpath); QGSettings *settings = NULL; const QByteArray id(KEYBINDINGS_CUSTOM_SCHEMA); if(QGSettings::isSchemaInstalled(id)) { if(bba.isEmpty()){ continue; } settings= new QGSettings(ba, bba); if(settings){ if(settings->keys().contains(BINDING_KEY)){ bingdingStr=settings->get(BINDING_KEY).toInt(); } } if(winId==bingdingStr){ settings->set(ACTION_KEY,"freeze"); } } if(settings){ settings->deleteLater(); } } } ukui-panel-3.0.6.4/plugin-tray/storagearrow.cpp0000644000175000017500000000631114204636772020066 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include #include "storagearrow.h" #include "../panel/customstyle.h" #include "../panel/iukuipanel.h" #define PANEL_SETTINGS "org.ukui.panel.settings" #define PANEL_POSITION_KEY "panelposition" #define ICON_SIZE_KEY "iconsize" storageArrowStatus state=NORMAL; StorageArrow::StorageArrow(QWidget* parent): QPushButton(parent) { setStyle(new CustomStyle()); // setVisible(false); QTimer::singleShot(10,[this]{setArrowIcon();}); const QByteArray id(PANEL_SETTINGS); gsetting = new QGSettings(id); panelPosition = gsetting->get(PANEL_POSITION_KEY).toInt(); iconsize=gsetting->get(ICON_SIZE_KEY).toInt(); connect(gsetting, &QGSettings::changed, this, [=] (const QString &key){ if(key == PANEL_POSITION_KEY){ panelPosition=gsetting->get(PANEL_POSITION_KEY).toInt(); setArrowIcon(); } if(key == ICON_SIZE_KEY){ iconsize=gsetting->get(ICON_SIZE_KEY).toInt(); setArrowIcon(); } }); } StorageArrow::~StorageArrow() { } //void StorageArrow::paintEvent(QEvent *e) //{ // QStyleOption opt; // opt.initFrom(this); // QPainter p(this); // switch(state) // { // case NORMAL: // p.setBrush(QColor(0xff,0xff,0xff,0x0f)); // p.setPen(Qt::NoPen); // break; // case HOVER: // p.setBrush(QColor(0xff,0xff,0xff,0x1f)); // p.setPen(Qt::NoPen); // break; // case PRESS: //// p.setBrush(Qt::green); // p.setPen(Qt::NoPen); // break; // } // p.setRenderHint(QPainter::Antialiasing); // 反锯齿; // p.drawRoundedRect(opt.rect,4,4); // style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); //} int StorageArrow::GetTaskbarInfo() { } void StorageArrow::setArrowIcon() { switch (panelPosition) { case 1: setIcon(QIcon::fromTheme("pan-down-symbolic")); break; case 2: setIcon(QIcon::fromTheme("pan-end-symbolic")); break; case 3: setIcon(QIcon::fromTheme("pan-start-symbolic")); break; default: setIcon(QIcon::fromTheme("pan-up-symbolic")); break; } setProperty("useIconHighlightEffect", 0x2); setIconSize(QSize(iconsize/2,iconsize/2)); setFixedSize(iconsize,iconsize * 1.3); } void StorageArrow::enterEvent(QEvent *) { repaint(); return; } void StorageArrow::leaveEvent(QEvent *) { repaint(); return; } ukui-panel-3.0.6.4/plugin-tray/ukuitrayplugin.cpp0000644000175000017500000000214514204636772020444 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see realign(); } ukui-panel-3.0.6.4/plugin-tray/trayicon.h0000644000175000017500000001045714204636772016652 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include #include #include #include //X11 #include #include //panel #include "../panel/highlight-effect.h" #define TRAY_ICON_SIZE_DEFAULT 16 class QWidget; class UKUIPanel; class IUKUIPanelPlugin; /** * @brief The TrayIcon class * 承载托盘应用 */ class TrayIcon: public QToolButton { Q_OBJECT /* * 负责与ukui桌面环境托盘应用通信的dbus * 在点击托盘图标外部托盘按钮内部的区域时发给其他托盘应用 点击信号 * 托盘应用收到此信号应实现 show/hide 主界面的操作 */ Q_CLASSINFO("D-Bus Interface", "com.ukui.panel.plugins.tray") enum EffectMode { HighlightOnly, BothDefaultAndHighlit }; Q_PROPERTY(QSize iconSize READ iconSize WRITE setIconSize) public: TrayIcon(Window iconId, QSize const & iconSize, QWidget* parent); virtual ~TrayIcon(); Window iconId() { return mIconId; } Window windowId() { return mWindowId; } void windowDestroyed(Window w); QSize iconSize() const { return mIconSize; } void setIconSize(QSize iconSize); /** * @brief moveMenu 右键菜单,移动图标至任务栏/收纳 */ void moveMenu(); QSize sizeHint() const; static QString mimeDataFormat() { return QLatin1String("x-ukui/tray-button"); } public slots: void notifyAppFreeze(); void emitIconId(); signals: void notifyTray(Window); void iconIsMoving(Window); void switchButtons(TrayIcon *from, TrayIcon *to); protected: bool event(QEvent *event); void draw(QPaintEvent* event); void enterEvent(QEvent *); void leaveEvent(QEvent *); void paintEvent(QPaintEvent *); //拖拽相关 void dragEnterEvent(QDragEnterEvent *e); void dragMoveEvent(QDragMoveEvent * e); void mouseMoveEvent(QMouseEvent *e); void mousePressEvent(QMouseEvent *e); virtual QMimeData * mimeData(); private: void init(); QRect iconGeometry(); void trayButtonPress(QMouseEvent *); bool needReDraw(); /** * @brief caculateMenuWindowPos * 计算右键菜单的位置 * @param absolutePos * @param windowSize menu的sizeHint * @return 返回值是QRect,可直接使用,无需转换 */ QRect caculateMenuWindowPos(QPoint const & absolutePos, QSize const & windowSize); QPixmap drawSymbolicColoredPixmap(const QPixmap &source); QPoint mDragStart; IUKUIPanelPlugin *mPlugin; Window mIconId; Window mWindowId; QSize mIconSize; Damage mDamage; Display* mDisplay; QMenu *menu; static bool isXCompositeAvailable(); QSize mRectSize; enum TrayAppStatus{NORMAL, HOVER, PRESS}; TrayAppStatus traystatus; QGSettings *scaling_settings; QGSettings *gsettings; // int tray_icon_color; bool dark_style; //适配高分屏 int x_panel; int y_panel; int x; int y; QGSettings *System_scale_gsettings; float scale=1; void trayButtonCoordinateMapping(int x,int y); }; /** * @brief The TrayButtonMimeData class * 拖拽托盘按钮的时候用到的TrayButtonMimeData */ class TrayButtonMimeData: public QMimeData { Q_OBJECT public: TrayButtonMimeData(): QMimeData(), mButton(0) { } TrayIcon *button() const { return mButton; } void setButton(TrayIcon *button) { mButton = button; } private: TrayIcon *mButton; }; #endif // TRAYICON_H ukui-panel-3.0.6.4/plugin-tray/ukuitrayplugin.h0000644000175000017500000000364514204636772020117 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include class UKUITray; class UKUITrayPlugin : public QObject, public IUKUIPanelPlugin { Q_OBJECT public: explicit UKUITrayPlugin(const IUKUIPanelPluginStartupInfo &startupInfo); ~UKUITrayPlugin(); virtual QWidget *widget(); virtual QString themeId() const { return "Tray"; } virtual Flags flags() const { return PreferRightAlignment | SingleInstance | NeedsHandle; } void realign(); bool isSeparate() const { return true; } private: UKUITray *mWidget; }; class UKUITrayPluginLibrary: public QObject, public IUKUIPanelPluginLibrary { Q_OBJECT // Q_PLUGIN_METADATA(IID "ukui.org/Panel/PluginInterface/3.0") Q_INTERFACES(IUKUIPanelPluginLibrary) public: IUKUIPanelPlugin *instance(const IUKUIPanelPluginStartupInfo &startupInfo) const { // Currently only X11 supported if (!QX11Info::connection()) { qWarning() << "Currently tray plugin supports X11 only. Skipping."; return nullptr; } return new UKUITrayPlugin(startupInfo); } }; #endif // UKUITRAYPLUGIN_H ukui-panel-3.0.6.4/plugin-tray/resources/0000755000175000017500000000000014204636772016654 5ustar fengfengukui-panel-3.0.6.4/plugin-tray/resources/trayAppSetting.sh0000755000175000017500000000135414204636772022174 0ustar fengfeng#!/bin/bash #for((i=0;i<20;i++)) for i in `seq 30` do #echo $i s="org.ukui.panel.tray:/org/ukui/tray/keybindings/custom${i}/"; #gsettings get "$s" name gsettingGetAppName=$(gsettings get "$s" name); trayAppName=\'$1\' #echo $gsettingGetAppName #echo $trayAppName if [ $gsettingGetAppName = $trayAppName ] then gsettings set org.ukui.panel.tray:/org/ukui/tray/keybindings/custom${i}/ record $2 gsettings set org.ukui.panel.tray:/org/ukui/tray/keybindings/custom${i}/ action $2 fi if [ $trayAppName = "'all'" ] then echo $trayAppName gsettings set org.ukui.panel.tray:/org/ukui/tray/keybindings/custom${i}/ record $2 gsettings set org.ukui.panel.tray:/org/ukui/tray/keybindings/custom${i}/ action $2 fi done ukui-panel-3.0.6.4/plugin-tray/resources/tray.desktop.in0000644000175000017500000000027114204636772021633 0ustar fengfeng[Desktop Entry] Type=Service ServiceTypes=UKUIPanel/Plugin Name=System tray Comment=Display applications minimized to the system tray. Icon=go-bottom #TRANSLATIONS_DIR=../translations ukui-panel-3.0.6.4/plugin-tray/CMakeLists.txt0000644000175000017500000000314014204636772017400 0ustar fengfengset(PLUGIN "tray") include(CheckLibraryExists) #find_package(XCB REQUIRED COMPONENTS xcb xcb-util xcb-damage) find_package(PkgConfig) find_package(X11 REQUIRED) find_package(Qt5X11Extras ${REQUIRED_QT_VERSION} REQUIRED) pkg_check_modules(XCOMPOSITE REQUIRED xcomposite) pkg_check_modules(XDAMAGE REQUIRED xdamage) pkg_check_modules(XRENDER REQUIRED xrender) pkg_check_modules(Gsetting REQUIRED gsettings-qt) pkg_check_modules(GIO2 REQUIRED gio-2.0) pkg_check_modules(GIOUNIX2 REQUIRED gio-unix-2.0) pkg_check_modules(DCONF REQUIRED dconf) include_directories(${Gsetting_INCLUDE_DIRS}) include_directories(${GIO2_INCLUDE_DIRS}) include_directories(${GIOUNIX2_INCLUDE_DIRS}) include_directories(${DCONF_INCLUDE_DIRS}) set(HEADERS ukuitrayplugin.h ukuitray.h trayicon.h xfitman.h ukuitraystrage.h ukuistoragewidget.h storagearrow.h traydynamicgsetting.h ) set(SOURCES ukuitrayplugin.cpp ukuitray.cpp trayicon.cpp xfitman.cpp ukuitraystrage.cpp ukuistoragewidget.cpp storagearrow.cpp traydynamicgsetting.cpp ) set(LIBRARIES ${X11_LIBRARIES} ${XCOMPOSITE_LDFLAGS} ${XDAMAGE_LIBRARIES} ${XRENDER_LIBRARIES} ${XCB_LIBRARIES} ${XTEST_LIBRARIES} libXtst.so Qt5X11Extras ${Gsetting_LIBRARIES} ${GIO2_LIBRARIES} ${GIOUNIX2_LIBRARIES} ${DCONF_LIBRARIES} ) install(FILES ../panel/resources/org.ukui.panel.tray.gschema.xml DESTINATION "/usr/share/glib-2.0/schemas/" COMPONENT Runtime ) install(FILES resources/trayAppSetting.sh DESTINATION "/usr/share/ukui/ukui-panel/plugin-tray/") BUILD_UKUI_PLUGIN(${PLUGIN}) ukui-panel-3.0.6.4/plugin-tray/ukuistoragewidget.h0000644000175000017500000000200414204636772020555 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include class UKUiStorageWidget : public QWidget { public: UKUiStorageWidget(); void setStorageWidgetButtonLayout(int size); protected: void paintEvent(QPaintEvent*); }; #endif // UKUISTORAGEWIDGET_H ukui-panel-3.0.6.4/plugin-tray/ukuitray.cpp0000644000175000017500000006616714204636772017243 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include #include #include "trayicon.h" #include "../panel/iukuipanel.h" #include "../panel/common/ukuigridlayout.h" #include "ukuitray.h" #include "xfitman.h" #include #include #include #include #include #include #include #include "ukuitrayplugin.h" #undef Bool // defined as int in X11/Xlib.h #include "../panel/iukuipanelplugin.h" #include #include #include #include #include "traydynamicgsetting.h" #define _NET_SYSTEM_TRAY_ORIENTATION_HORZ 0 #define _NET_SYSTEM_TRAY_ORIENTATION_VERT 1 #define SYSTEM_TRAY_REQUEST_DOCK 0 #define SYSTEM_TRAY_BEGIN_MESSAGE 1 #define SYSTEM_TRAY_CANCEL_MESSAGE 2 #define XEMBED_EMBEDDED_NOTIFY 0 #define XEMBED_MAPPED (1 << 0) #define mWinWidth 46 #define mWinHeight 46 /* qt会将glib里的signals成员识别为宏,所以取消该宏 * 后面如果用到signals时,使用Q_SIGNALS代替即可 **/ #ifdef signals #undef signals #endif extern "C" { #include #include #include } #define KEYBINDINGS_CUSTOM_SCHEMA "org.ukui.panel.tray" #define KEYBINDINGS_CUSTOM_DIR "/org/ukui/tray/keybindings/" #define ACTION_KEY "action" #define RECORD_KEY "record" #define BINDING_KEY "binding" #define NAME_KEY "name" #define TRAY_APP_COUNT 16 #define PANEL_SETTINGS "org.ukui.panel.settings" #define PANEL_LINES "panellines" #define TRAY_LINE "traylines" #define PANEL_SIZE "panelsize" #define ICON_SIZE "iconsize" bool flag=false; extern storageBarStatus status; UKUITray::UKUITray(UKUITrayPlugin *plugin, QWidget *parent): QFrame(parent), mValid(false), mTrayId(0), mDamageEvent(0), mDamageError(0), mIconSize(TRAY_ICON_SIZE_DEFAULT, TRAY_ICON_SIZE_DEFAULT), mPlugin(plugin), mDisplay(QX11Info::display()) { qDebug()<<"Plugin-Tray :: UKUITray start"; m_pwidget = NULL; status=ST_HIDE; const QByteArray id(PANEL_SETTINGS); if(QGSettings::isSchemaInstalled(id)) { settings=new QGSettings(id); } connect(settings, &QGSettings::changed, this, [=] (const QString &key){ if(key==ICON_SIZE){ trayIconSizeRefresh(); handleStorageUi(); } }); mLayout = new UKUi::GridLayout(this); setLayout(mLayout); _NET_SYSTEM_TRAY_OPCODE = XfitMan::atom("_NET_SYSTEM_TRAY_OPCODE"); // Init the selection later just to ensure that no signals are sent until // after construction is done and the creating object has a chance to connect. QTimer::singleShot(3, this, SLOT(startTray())); mBtn =new StorageArrow(this); mLayout->addWidget(mBtn); storageFrame=new UKUIStorageFrame; // fix 任务栏可隐藏时,鼠标放到traystorage时任务栏也会隐藏问题 mPlugin->willShowWindow(storageFrame); mStorageLayout = new UKUi::GridLayout(storageFrame); storageFrame->setLayout(mStorageLayout); handleStorageUi(); connect(mBtn,SIGNAL(clicked()),this,SLOT(storageBar())); mBtn->setVisible(true); realign(); //进入桌面后可能存在的托盘区域未刷新问题 QTimer::singleShot(100,[this] { realign(); trayIconSizeRefresh(); }); //针对ukui桌面环境特殊应用的处理,保证稳定性 //QTimer::singleShot(3000,[this] { panelStartupFcitx();}); QTimer::singleShot(30000,[this] { //QProcess::execute("sh /usr/share/ukui/ukui-panel/plugin-tray/trayAppSetting.sh"); }); QDBusConnection::sessionBus().connect(QString(), QString("/taskbar/click"), "com.ukui.panel.plugins.taskbar", "sendToUkuiDEApp", this, SLOT(hideStorageWidget())); qDebug()<<"Plugin-Tray :: UKUITray end"; } UKUITray::~UKUITray() { // for(int i = 0; i < mIcons.size(); i++) // { // if(mIcons[i]) // { // mIcons[i]->deleteLater(); // mIcons[i] = NULL; // } // } // mIcons.clear(); // mStorageIcons.clear(); // mTrayIcons.clear(); freezeApp(); stopTray(); } void UKUITray::storageBar() { if(mStorageIcons.size()<1) mBtn->setVisible(false); if(status==ST_HIDE) { status = ST_SHOW; showAndHideStorage(false); } else { status = ST_HIDE; showAndHideStorage(true); } realign(); } void UKUITray::hideStorageWidget() { status = ST_HIDE; showAndHideStorage(true); } void UKUITray::showAndHideStorage(bool storageStatus) { if(storageStatus){ storageFrame->hide(); }else{ storageFrame->show(); handleStorageUi(); } } bool UKUITray::nativeEventFilter(const QByteArray &eventType, void *message, long *) { if (eventType != "xcb_generic_event_t") return false; xcb_generic_event_t* event = static_cast(message); TrayIcon* icon; int event_type = event->response_type & ~0x80; switch (event_type) { /* 监听到托盘应用的启动事件 */ case ClientMessage: clientMessageEvent(event); repaint(); break; // case ConfigureNotify: // icon = findIcon(event->xconfigure.window); // if (icon) // icon->configureEvent(&(event->xconfigure)); // break; /* * 监听到托盘应用的退出事件 */ case DestroyNotify: { /* * 在这里本应该刷新收纳栏 handleStorageUi() * 由于收纳栏不刷新可能会导致任务栏的崩溃 * 在freeze信号接受的地方freezeTrayApp()同样进行刷新收纳栏的操作 * 但是如果在这里刷新收纳栏目会导致收纳栏的应用异常退出 */ unsigned long event_window; event_window = reinterpret_cast(event)->window; icon = findIcon(event_window); if (icon) { icon->windowDestroyed(event_window); mTrayIcons.removeAll(icon); mStorageIcons.removeAll(icon); delete icon; } break; } default: if (event_type == mDamageEvent + XDamageNotify) { xcb_damage_notify_event_t* dmg = reinterpret_cast(event); icon = findIcon(dmg->drawable); if (icon) icon->update(); } break; } return false; } void UKUITray::realign() { mLayout->setEnabled(false); IUKUIPanel *panel = mPlugin->panel(); /* 刷新托盘收纳栏界面 * 不要在这里对收纳栏的图标执setFixedSize和setIconSize的操作 * 这些应该在handleStorageUi()函数中执行 * handleStorageUi(); */ if (panel->isHorizontal()){ dynamic_cast(mLayout)->setRowCount(panel->lineCount()); dynamic_cast(mLayout)->setColumnCount(0); } else{ dynamic_cast(mLayout)->setColumnCount(panel->lineCount()); dynamic_cast(mLayout)->setRowCount(0); } if(storageFrame){ int storageFramePosition; if(mPlugin->panel()->isHorizontal()){ storageFramePosition=(storageFrame->size().width()-mBtn->size().width())/2; storageFrame->setGeometry(mPlugin->panel()->calculatePopupWindowPos(mapToGlobal(QPoint(-storageFramePosition,0)), storageFrame->size())); } else{ storageFramePosition=(storageFrame->size().height()-mBtn->size().height())/2; storageFrame->setGeometry(mPlugin->panel()->calculatePopupWindowPos(mapToGlobal(QPoint(0,-storageFramePosition)), storageFrame->size())); } } if(mStorageIcons.size()<1) mBtn->setVisible(true); mLayout->setEnabled(true); #if 0 //设置任务栏 for(int i=0;ipanel()->isHorizontal()){ mIcons.at(i)->setFixedSize(mPlugin->panel()->iconSize(),mPlugin->panel()->panelSize()); }else{ mIcons.at(i)->setFixedSize(mPlugin->panel()->panelSize(),mPlugin->panel()->iconSize()); } mIcons.at(i)->setIconSize(QSize(mPlugin->panel()->iconSize()/2,mPlugin->panel()->iconSize()/2)); }else{ qDebug()<<"错误的托盘图标"; } } } /*监听托盘事件*/ void UKUITray::clientMessageEvent(xcb_generic_event_t *e) { unsigned long opcode; unsigned long message_type; Window id; xcb_client_message_event_t* event = reinterpret_cast(e); uint32_t* data32 = event->data.data32; message_type = event->type; opcode = data32[1]; if(message_type != _NET_SYSTEM_TRAY_OPCODE) return; switch (opcode) { case SYSTEM_TRAY_REQUEST_DOCK: id = data32[2]; if(id){ regulateIcon(&id); trayIconSizeRefresh(); } case SYSTEM_TRAY_BEGIN_MESSAGE: case SYSTEM_TRAY_CANCEL_MESSAGE: // qDebug() << "we don't show balloon messages."; break; default: // if (opcode == xfitMan().atom("_NET_SYSTEM_TRAY_MESSAGE_DATA")) // qDebug() << "message from dockapp:" << e->data.b; // else // qDebug() << "SYSTEM_TRAY : unknown message type" << opcode; break; } } /*遍历mIcons中的TrayIcon*/ TrayIcon* UKUITray::findIcon(Window id) { #if (QT_VERSION < QT_VERSION_CHECK(5,7,0)) for(int i=0;i= QT_VERSION_CHECK(5,7,0)) for(TrayIcon* icon : qAsConst(mIcons) ){ #endif if (icon->iconId() == id || icon->windowId() == id) return icon; } return 0; } TrayIcon* UKUITray::findTrayIcon(Window id) { #if (QT_VERSION < QT_VERSION_CHECK(5,7,0)) for(int i=0;i= QT_VERSION_CHECK(5,7,0)) for(TrayIcon* trayicon : qAsConst(mTrayIcons) ){ #endif if (trayicon->iconId() == id || trayicon->windowId() == id) return trayicon; } return 0; } TrayIcon* UKUITray::findStorageIcon(Window id) { #if (QT_VERSION < QT_VERSION_CHECK(5,7,0)) for(int i=0;i= QT_VERSION_CHECK(5,7,0)) for(TrayIcon* storageicon :qAsConst(mStorageIcons)){ #endif if (storageicon->iconId() == id || storageicon->windowId() == id) return storageicon; } return 0; } void UKUITray::setIconSize() { mIconSize=QSize(mPlugin->panel()->iconSize()/2,mPlugin->panel()->iconSize()/2); unsigned long size = qMin(mIconSize.width(), mIconSize.height()); XChangeProperty(mDisplay, mTrayId, XfitMan::atom("_NET_SYSTEM_TRAY_ICON_SIZE"), XA_CARDINAL, 32, PropModeReplace, (unsigned char*)&size, 1); } VisualID UKUITray::getVisual() { VisualID visualId = 0; Display* dsp = mDisplay; XVisualInfo templ; templ.screen=QX11Info::appScreen(); templ.depth=32; templ.c_class=TrueColor; int nvi; XVisualInfo* xvi = XGetVisualInfo(dsp, VisualScreenMask|VisualDepthMask|VisualClassMask, &templ, &nvi); if (xvi) { int i; XRenderPictFormat* format; for (i = 0; i < nvi; i++){ format = XRenderFindVisualFormat(dsp, xvi[i].visual); if (format && format->type == PictTypeDirect && format->direct.alphaMask) { visualId = xvi[i].visualid; break; } } XFree(xvi); } return visualId; } /** * @brief UKUITray::startTray * freedesktop系统托盘规范 */ void UKUITray::startTray() { Display* dsp = mDisplay; Window root = QX11Info::appRootWindow(); QString s = QString("_NET_SYSTEM_TRAY_S%1").arg(DefaultScreen(dsp)); Atom _NET_SYSTEM_TRAY_S = XfitMan::atom(s.toLatin1()); //this limit the tray apps | will not run more Same apps if (XGetSelectionOwner(dsp, _NET_SYSTEM_TRAY_S) != None){ qWarning() << "Another systray is running"; mValid = false; return; } // init systray protocol mTrayId = XCreateSimpleWindow(dsp, root, -1, -1, 1, 1, 0, 0, 0); XSetSelectionOwner(dsp, _NET_SYSTEM_TRAY_S, mTrayId, CurrentTime); if (XGetSelectionOwner(dsp, _NET_SYSTEM_TRAY_S) != mTrayId){ qWarning() << "Can't get systray manager"; stopTray(); mValid = false; return; } int orientation = _NET_SYSTEM_TRAY_ORIENTATION_HORZ; XChangeProperty(dsp, mTrayId, XfitMan::atom("_NET_SYSTEM_TRAY_ORIENTATION"), XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &orientation, 1); // ** Visual ******************************** VisualID visualId = getVisual(); if (visualId){ XChangeProperty(mDisplay, mTrayId, XfitMan::atom("_NET_SYSTEM_TRAY_VISUAL"), XA_VISUALID, 32, PropModeReplace, (unsigned char*)&visualId, 1); } setIconSize(); XClientMessageEvent ev; ev.type = ClientMessage; ev.window = root; ev.message_type = XfitMan::atom("MANAGER"); ev.format = 32; ev.data.l[0] = CurrentTime; ev.data.l[1] = _NET_SYSTEM_TRAY_S; ev.data.l[2] = mTrayId; ev.data.l[3] = 0; ev.data.l[4] = 0; XSendEvent(dsp, root, False, StructureNotifyMask, (XEvent*)&ev); XDamageQueryExtension(mDisplay, &mDamageEvent, &mDamageError); mValid = true; qApp->installNativeEventFilter(this); } void UKUITray::stopTray() { for (auto & icon : mIcons) disconnect(icon, &QObject::destroyed, this, &UKUITray::onIconDestroyed); qDeleteAll(mIcons); if (mTrayId){ XDestroyWindow(mDisplay, mTrayId); mTrayId = 0; } mValid = false; } //void UKUITray::stopStorageTray() //{ // for (auto & icon : mStorageIcons) // disconnect(icon, &QObject::destroyed, this, &UKUITray::onIconDestroyed); // qDeleteAll(mStorageIcons); // if (mTrayId){ // XDestroyWindow(mDisplay, mTrayId); // mTrayId = 0; // } //} void UKUITray::onIconDestroyed(QObject * icon) { //in the time QOjbect::destroyed is emitted, the child destructor //is already finished, so the qobject_cast to child will return nullptr in all cases mIcons.removeAll(static_cast(icon)); mStorageIcons.removeAll(static_cast(icon)); } void UKUITray::addTrayIcon(Window winId) { // decline to add an icon for a window we already manage TrayIcon *icon = findTrayIcon(winId); if(icon) return; else{ icon = new TrayIcon(winId, mIconSize, this); mIcons.append(icon); mTrayIcons.append(icon); mLayout->addWidget(icon); connect(icon, SIGNAL(switchButtons(TrayIcon*,TrayIcon*)), this, SLOT(switchButtons(TrayIcon*,TrayIcon*))); connect(icon,&QObject::destroyed,icon,&TrayIcon::notifyAppFreeze); connect(icon,&TrayIcon::notifyTray,[=](Window id){ freezeTrayApp(id);}); connect(icon, &QObject::destroyed, this, &UKUITray::onIconDestroyed); } } void UKUITray::addStorageIcon(Window winId) { TrayIcon *storageicon = findStorageIcon(winId); if(storageicon) return; else{ storageicon = new TrayIcon(winId, mIconSize, this); mIcons.append(storageicon); mStorageIcons.append(storageicon); //storageLayout->addWidget(storageicon); connect(storageicon,&QObject::destroyed,storageicon,&TrayIcon::notifyAppFreeze); connect(storageicon,&TrayIcon::notifyTray,[=](Window id){freezeTrayApp(id);}); connect(storageicon, &QObject::destroyed, this, &UKUITray::onIconDestroyed); if(mStorageIcons.size() > 0){ if(!mBtn->isVisible()){ mBtn->setVisible(true); } } } } /*与控制面板交互,移动应用到托盘栏或者收纳栏*/ void UKUITray::moveIconToTray(Window winId) { TrayIcon *storageicon = findStorageIcon(winId); if(!storageicon) return; else{ mStorageIcons.removeOne(storageicon); //storageLayout->removeWidget(storageicon); disconnect(storageicon, &QObject::destroyed, this, &UKUITray::onIconDestroyed); mTrayIcons.append(storageicon); mLayout->addWidget(storageicon); if(mStorageIcons.size() > 0){ handleStorageUi(); } else{ mBtn->setVisible(false); } connect(storageicon,&QObject::destroyed,storageicon,&TrayIcon::notifyAppFreeze); connect(storageicon,&TrayIcon::notifyTray,[this](Window id){freezeTrayApp(id);}); connect(storageicon, &QObject::destroyed, this, &UKUITray::onIconDestroyed); } trayIconSizeRefresh(); handleStorageUi(); } void UKUITray::moveIconToStorage(Window winId) { TrayIcon *icon = findTrayIcon(winId); if(!icon) return; else{ mLayout->removeWidget(icon); mTrayIcons.removeOne(icon); disconnect(icon, &QObject::destroyed, this, &UKUITray::onIconDestroyed); mStorageIcons.append(icon); if(mStorageIcons.size() > 0){ if(!mBtn->isVisible()){ mBtn->setVisible(true); } handleStorageUi(); } else{ mBtn->setVisible(false); } connect(icon,&QObject::destroyed,icon,&TrayIcon::notifyAppFreeze); connect(icon,&TrayIcon::notifyTray,[this](Window id){freezeTrayApp(id);}); connect(icon, &QObject::destroyed, this, &UKUITray::onIconDestroyed); } handleStorageUi(); } void UKUITray::regulateIcon(Window *mid) { int wid=(int)*mid; int count=0; QList existsPath = listExistsPath(); QString actionStr; int bingdingStr; QString nameStr; //匹配表中存在的name与该wid的name,若相等则用新的wid覆盖旧的wid,否则在表中添加新的路径,写上新的wid,name,以及状态。 for (char * path : existsPath) { QString p =KEYBINDINGS_CUSTOM_DIR; std::string str = p.toStdString(); const int len = str.length(); char * prepath = new char[len+1]; strcpy(prepath,str.c_str()); char * allpath = strcat(prepath, path); const QByteArray bba(allpath); QGSettings *settings = NULL; const QByteArray id(KEYBINDINGS_CUSTOM_SCHEMA); if(QGSettings::isSchemaInstalled(id)) { if(bba.isEmpty()){ free(allpath); free(prepath); continue; } settings= new QGSettings(id, bba); if(settings){ if(settings->keys().contains(RECORD_KEY)){ settings->set(ACTION_KEY,settings->get(RECORD_KEY).toString()); } if(settings->keys().contains(ACTION_KEY)){ actionStr = settings->get(ACTION_KEY).toString(); } if(settings->keys().contains(NAME_KEY)){ nameStr = settings->get(NAME_KEY).toString(); } if(nameStr=="" || nameStr=="ErrorApplication"){ settings->reset(NAME_KEY); settings->reset(BINDING_KEY); settings->reset(ACTION_KEY); settings->reset(RECORD_KEY); } } if(nameStr==xfitMan().getApplicationName(wid)) { if(nameStr=="fcitx") { fcitx_flag=true; } settings->set(BINDING_KEY, wid); bingdingStr=wid; if(QString::compare(actionStr,"tray")==0){ addTrayIcon(bingdingStr); // TrayIcon *icon = findTrayIcon(bingdingStr); // connect(icon,&TrayIcon::iconIsMoving,[this](Window id){moveIconToStorage(id);}); } if(QString::compare(actionStr,"storage")==0){ addStorageIcon(bingdingStr); // TrayIcon *icon = findStorageIcon(bingdingStr); // connect(icon,&TrayIcon::iconIsMoving,[this](Window id){moveIconToTray(id);}); } connect(settings, &QGSettings::changed, this, [=] (const QString &key){ if(key=="action"){ if(QString::compare(settings->get(ACTION_KEY).toString(),"tray")==0){ moveIconToTray(bingdingStr); // TrayIcon *icon = findStorageIcon(bingdingStr); // connect(icon,&TrayIcon::iconIsMoving,[this](Window id){moveIconToTray(id);}); } else if(QString::compare(settings->get(ACTION_KEY).toString(),"storage")==0){ moveIconToStorage(bingdingStr); // TrayIcon *icon = findTrayIcon(bingdingStr); // connect(icon,&TrayIcon::iconIsMoving,[this](Window id){moveIconToStorage(id);}); } else if(QString::compare(settings->get(ACTION_KEY).toString(),"freeze")==0){ } } }); delete allpath; break; } } settings->deleteLater(); delete prepath; count++; g_free(path); } if(count >= existsPath.count()) { newAppDetect(wid); count++; } } QStringList UKUITray::getShowInTrayApp() { QString filename = "/usr/share/ukui/ukui-panel/panel-commission.ini"; QSettings m_settings(filename, QSettings::IniFormat); m_settings.setIniCodec("UTF-8"); m_settings.beginGroup("ShowInTray"); QStringList trayAppList = m_settings.value("trayname", "").toStringList(); qDebug()<<"trayAppList :"<set(BINDING_KEY,wid); newsetting->set(NAME_KEY,xfitMan().getApplicationName(wid)); QStringList trayIconNameList = getShowInTrayApp(); //trayIconNameList<<"ukui-volume-control-applet-qt"<<"kylin-nm"<<"ukui-sidebar"<<"indicator-china-weather"<<"ukui-flash-disk"<<"fcitx"<<"sogouimebs-qimpanel"<<"fcitx-qimpanel"<<"explorer.exe"<<"ukui-power-manager-tray"<<"baidu-qimpanel"<<"iflyime-qim"; if(trayIconNameList.contains(xfitMan().getApplicationName(wid))){ newsetting->set(ACTION_KEY,"tray"); newsetting->set(RECORD_KEY,"tray"); addTrayIcon(wid); } else{ newsetting->set(ACTION_KEY,"storage"); newsetting->set(RECORD_KEY,"storage"); addStorageIcon(wid); } } delete newsetting; QGSettings* settings; const QByteArray keyId(KEYBINDINGS_CUSTOM_SCHEMA); if(QGSettings::isSchemaInstalled(keyId)){ settings= new QGSettings(id, idd,this); connect(settings, &QGSettings::changed, this, [=] (const QString &key){ if(key=="action"){ if(QString::compare(settings->get(ACTION_KEY).toString(),"tray")==0){ moveIconToTray(wid); } else if(QString::compare(settings->get(ACTION_KEY).toString(),"storage")==0){ moveIconToStorage(wid); } else{ qDebug()<<"get error action"; qWarning()<<"get error action"; } } }); } } void UKUITray::handleStorageUi() { if(m_pwidget) { if(mStorageLayout->count()){ mStorageLayout->removeWidget(m_pwidget); } UKUi::GridLayout *vLayout = dynamic_cast(m_pwidget->layout()); if(vLayout) { vLayout->deleteLater(); } m_pwidget->deleteLater(); m_pwidget = NULL; } m_pwidget = new UKUiStorageWidget; m_pwidget->setStorageWidgetButtonLayout(mStorageIcons.size()); for(auto it = mStorageIcons.begin();it != mStorageIcons.end();++it) { m_pwidget->layout()->addWidget(*it); (*it)->setFixedSize(mWinWidth,mWinHeight); } storageFrame->layout()->addWidget(m_pwidget); storageFrame->setStorageFrameSize(mStorageIcons.size()); } void UKUITray::contextMenuEvent(QContextMenuEvent *event) { } void UKUITray::switchButtons(TrayIcon *button1, TrayIcon *button2) { if (button1 == button2) return; int n1 = mLayout->indexOf(button1); int n2 = mLayout->indexOf(button2); int l = qMin(n1, n2); int m = qMax(n1, n2); mLayout->moveItem(l, m); mLayout->moveItem(m-1, l); } //特殊处理 //任务栏异常退出可能导致输入法异常,此时任务栏再次起来不会重新拉起输入法,此处特殊处理 void UKUITray::panelStartupFcitx() { if(!fcitx_flag){ qDebug()<<"fcitx未启动"; QProcess *process =new QProcess(this); process->startDetached("fcitx"); process->deleteLater(); } } ukui-panel-3.0.6.4/plugin-tray/traydynamicgsetting.h0000644000175000017500000000271014204636772021104 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include //x11 #include /** * 通过设置gsetting来调节应用在托盘或者收纳 * 以下listExistsPath findFreePath */ /** * @brief listExistsPath * @return * * 列出存在的可供gsettings使用的路径 */ QList listExistsPath(); QString findFreePath(); /** * @brief freezeTrayApp * @param winId * 将托盘应用置为freeze的状态 */ void freezeTrayApp(int winId); /** * @brief freezeApp * 将所有的托盘应用的状态至为freeze * 一般存在与在任务栏退出的时候 */ void freezeApp(); #endif // TRAYDYNAMICGSETTING_H ukui-panel-3.0.6.4/plugin-tray/ukuistoragewidget.cpp0000644000175000017500000000772214204636772021124 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see //paint #include #include #include #include #include //layout #include "../panel/common/ukuigridlayout.h" //收纳栏目图标布局 UKUiStorageWidget::UKUiStorageWidget() { setAttribute(Qt::WA_TranslucentBackground);//设置窗口背景透明 } void UKUiStorageWidget::paintEvent(QPaintEvent *event) { QStyleOption opt; opt.init(this); QPainter p(this); p.setBrush(QBrush(QColor(0x13,0x14,0x14,0x4d))); p.setPen(Qt::NoPen); p.setRenderHint(QPainter::Antialiasing); p.drawRoundedRect(opt.rect,6,6); style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); } #define mWinWidth 46 #define mWinHeight 46 void UKUiStorageWidget::setStorageWidgetButtonLayout(int size) { int winWidth = 0; int winHeight = 0; this->setLayout(new UKUi::GridLayout); switch(size) { case 1: winWidth = mWinWidth; winHeight = mWinHeight; this->setFixedSize(winWidth,winHeight); dynamic_cast(this->layout())->setColumnCount(1); dynamic_cast(this->layout())->setRowCount(1); break; case 2: winWidth = mWinWidth*2; winHeight = mWinHeight; this->setFixedSize(winWidth,winHeight); dynamic_cast(this->layout())->setColumnCount(2); dynamic_cast(this->layout())->setRowCount(1); break; case 3: winWidth = mWinWidth*3; winHeight = mWinHeight; this->setFixedSize(winWidth,winHeight); dynamic_cast(this->layout())->setColumnCount(3); dynamic_cast(this->layout())->setRowCount(1); break; case 4 ... 6: winWidth = mWinWidth*3; winHeight = mWinHeight*2; this->setFixedSize(winWidth,winHeight); dynamic_cast(this->layout())->setColumnCount(3); dynamic_cast(this->layout())->setRowCount(2); break; case 7 ... 9: winWidth = mWinWidth*3; winHeight = mWinHeight*3; this->setFixedSize(winWidth,winHeight); dynamic_cast(this->layout())->setColumnCount(3); dynamic_cast(this->layout())->setRowCount(3); break; case 10 ... 12: winWidth = mWinWidth*3; winHeight = mWinHeight*4; this->setFixedSize(winWidth,winHeight); dynamic_cast(this->layout())->setColumnCount(3); dynamic_cast(this->layout())->setRowCount(4); break; case 13 ... 40: //默认情况下的布局 winWidth = mWinWidth*4; winHeight = mWinHeight*4; this->setFixedSize(winWidth,winHeight); dynamic_cast(this->layout())->setColumnCount(4); // dynamic_cast(this->layout())->setRowCount(7); break; default: // winWidth = 0; winHeight = 0; this->setFixedSize(winWidth,winHeight); dynamic_cast(this->layout())->setColumnCount(4); // dynamic_cast(this->layout())->setRowCount(7); break; } } ukui-panel-3.0.6.4/plugin-tray/xfitman.cpp0000644000175000017500000002053714204636772017023 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see // #include // #include // #include // #include #include #include #include "xfitman.h" #include #include #include /** * @file xfitman.cpp * @brief implements class Xfitman * @author Christopher "VdoP" Regali */ /* S ome requests from Cli*ents include type of the Client, for example the _NET_ACTIVE_WINDOW message. Currently the types can be 1 for normal applications, and 2 for pagers. See http://standards.freedesktop.org/wm-spec/latest/ar01s09.html#sourceindication */ #define SOURCE_NORMAL 1 #define SOURCE_PAGER 2 const XfitMan& xfitMan() { static XfitMan instance; return instance; } /** * @brief constructor: gets Display vars and registers us */ XfitMan::XfitMan() { root = (Window)QX11Info::appRootWindow(); } Atom XfitMan::atom(const char* atomName) { static QHash hash; if (hash.contains(atomName)) return hash.value(atomName); Atom atom = XInternAtom(QX11Info::display(), atomName, false); hash[atomName] = atom; return atom; } /** * @brief moves a window to a new position */ void XfitMan::moveWindow(Window _win, int _x, int _y) const { XMoveWindow(QX11Info::display(), _win, _x, _y); } /************************************************ ************************************************/ bool XfitMan::getWindowProperty(Window window, Atom atom, // property Atom reqType, // req_type unsigned long* resultLen,// nitems_return unsigned char** result // prop_return ) const { int format; unsigned long type, rest; return XGetWindowProperty(QX11Info::display(), window, atom, 0, 4096, false, reqType, &type, &format, resultLen, &rest, result) == Success; } /************************************************ ************************************************/ bool XfitMan::getRootWindowProperty(Atom atom, // property Atom reqType, // req_type unsigned long* resultLen,// nitems_return unsigned char** result // prop_return ) const { return getWindowProperty(root, atom, reqType, resultLen, result); } /** * @brief resizes a window to the given dimensions */ void XfitMan::resizeWindow(Window _wid, int _width, int _height) const { XResizeWindow(QX11Info::display(), _wid, _width, _height); } /** * @brief gets a windowpixmap from a window */ bool XfitMan::getClientIcon(Window _wid, QPixmap& _pixreturn) const { int format; ulong type, nitems, extra; ulong* data = 0; XGetWindowProperty(QX11Info::display(), _wid, atom("_NET_WM_ICON"), 0, LONG_MAX, False, AnyPropertyType, &type, &format, &nitems, &extra, (uchar**)&data); if (!data) { return false; } QImage img (data[0], data[1], QImage::Format_ARGB32); for (int i=0; iaddPixmap(QPixmap::fromImage(img)); } XFree(data); return true; } /** * @brief destructor */ XfitMan::~XfitMan() { } /** * @brief returns a windowname and sets _nameSource to the finally used Atom */ // i got the idea for this from taskbar-plugin of LXPanel - so credits fly out :) QString XfitMan::getWindowTitle(Window _wid) const { QString name = ""; //first try the modern net-wm ones unsigned long length; unsigned char *data = NULL; Atom utf8Atom = atom("UTF8_STRING"); if (getWindowProperty(_wid, atom("_NET_WM_VISIBLE_NAME"), utf8Atom, &length, &data)) { name = QString::fromUtf8((char*) data); XFree(data); } if (name.isEmpty()) { if (getWindowProperty(_wid, atom("_NET_WM_NAME"), utf8Atom, &length, &data)) { name = QString::fromUtf8((char*) data); XFree(data); } } if (name.isEmpty()) { if (getWindowProperty(_wid, atom("XA_WM_NAME"), XA_STRING, &length, &data)) { name = (char*) data; XFree(data); } } if (name.isEmpty()) { Status ok = XFetchName(QX11Info::display(), _wid, (char**) &data); name = QString((char*) data); if (0 != ok) XFree(data); } if (name.isEmpty()) { XTextProperty prop; if (XGetWMName(QX11Info::display(), _wid, &prop)) { name = QString::fromUtf8((char*) prop.value); XFree(prop.value); } } return name; } QString XfitMan::getApplicationName(Window _wid) const { XClassHint hint; QString ret; if (XGetClassHint(QX11Info::display(), _wid, &hint)) { if (hint.res_name) { ret = hint.res_name; XFree(hint.res_name); } if (hint.res_class) { XFree(hint.res_class); } } return ret; } /** * @brief sends a clientmessage to a window */ int XfitMan::clientMessage(Window _wid, Atom _msg, unsigned long data0, unsigned long data1, unsigned long data2, unsigned long data3, unsigned long data4) const { XClientMessageEvent msg; msg.window = _wid; msg.type = ClientMessage; msg.message_type = _msg; msg.send_event = true; msg.display = QX11Info::display(); msg.format = 32; msg.data.l[0] = data0; msg.data.l[1] = data1; msg.data.l[2] = data2; msg.data.l[3] = data3; msg.data.l[4] = data4; if (XSendEvent(QX11Info::display(), root, false, (SubstructureRedirectMask | SubstructureNotifyMask) , (XEvent *) &msg) == Success) return EXIT_SUCCESS; else return EXIT_FAILURE; } /** * @brief raises windows _wid */ void XfitMan::raiseWindow(Window _wid) const { clientMessage(_wid, atom("_NET_ACTIVE_WINDOW"), SOURCE_PAGER); } /************************************************ ************************************************/ void XfitMan::closeWindow(Window _wid) const { clientMessage(_wid, atom("_NET_CLOSE_WINDOW"), 0, // Timestamp SOURCE_PAGER); } void XfitMan::setIconGeometry(Window _wid, QRect* rect) const { Atom net_wm_icon_geometry = atom("_NET_WM_ICON_GEOMETRY"); if(!rect) XDeleteProperty(QX11Info::display(), _wid, net_wm_icon_geometry); else { long data[4]; data[0] = rect->x(); data[1] = rect->y(); data[2] = rect->width(); data[3] = rect->height(); XChangeProperty(QX11Info::display(), _wid, net_wm_icon_geometry, XA_CARDINAL, 32, PropModeReplace, (unsigned char*)data, 4); } } ukui-panel-3.0.6.4/plugin-tray/ukuitraystrage.h0000644000175000017500000000403514204636772020100 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include #include #include "fixx11h.h" #include #include #include #include #include #include #include #include "../panel/iukuipanel.h" #include "../panel/customstyle.h" #include "../panel/ukuicontrolstyle.h" #include #include #include #include "trayicon.h" #include "../panel/ukuipanellayout.h" #include "../panel/common/ukuigridlayout.h" #include "../panel/common_fun/listengsettings.h" #include "xfitman.h" class UKUiStorageWidget; enum storageBarStatus{ST_HIDE,ST_SHOW}; /** * @brief This makes our storage * 此界面是收纳的主窗口,里面添加了一个UKUiStorageWidget */ class UKUIStorageFrame:public QWidget { Q_OBJECT public: UKUIStorageFrame(QWidget* parent =0); ~UKUIStorageFrame(); void setStorageFrameSize(int size); void setStorageFramGeometry(); protected: bool eventFilter(QObject *, QEvent *); void paintEvent(QPaintEvent *event)override; private: Atom _NET_SYSTEM_TRAY_OPCODE; int panelsize; int iconsize; int panelPosition; private slots: void hideStorageFrame(); }; #endif ukui-panel-3.0.6.4/plugin-tray/xfitman.h0000644000175000017500000000534714204636772016472 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see /** * @file xfitman.h * @author Christopher "VdoP" Regali * @brief handles all of our xlib-calls. */ /** * @brief manages the Xlib apicalls */ class XfitMan { public: XfitMan(); ~XfitMan(); static Atom atom(const char* atomName); void moveWindow(Window _win, int _x, int _y) const; void raiseWindow(Window _wid) const; void resizeWindow(Window _wid, int _width, int _height) const; void closeWindow(Window _wid) const; bool getClientIcon(Window _wid, QPixmap& _pixreturn) const; bool getClientIcon(Window _wid, QIcon *icon) const; void setIconGeometry(Window _wid, QRect* rect = 0) const; QString getWindowTitle(Window _wid) const; QString getApplicationName(Window _wid) const; int clientMessage(Window _wid, Atom _msg, long unsigned int data0, long unsigned int data1 = 0, long unsigned int data2 = 0, long unsigned int data3 = 0, long unsigned int data4 = 0) const; private: /** \warning Do not forget to XFree(result) after data are processed! */ bool getWindowProperty(Window window, Atom atom, // property Atom reqType, // req_type unsigned long* resultLen,// nitems_return unsigned char** result // prop_return ) const; /** \warning Do not forget to XFree(result) after data are processed! */ bool getRootWindowProperty(Atom atom, // property Atom reqType, // req_type unsigned long* resultLen,// nitems_return unsigned char** result // prop_return ) const; Window root; //the actual root window on the used screen }; const XfitMan& xfitMan(); #endif // UKUIXFITMAN_H ukui-panel-3.0.6.4/AUTHORS0000644000175000017500000000056314203402514013423 0ustar fengfengUpstream Authors: LXQT team: https://lxqt.org Razor team: http://razor-qt.org kylin team: https://www.ukui.com Copyright: Copyright (c) 2010-2012 Razor team Copyright (c) 2012-2017 iLXQT team Copyright (c) 2019 Tianjin KYLIN Information Technology Co., Ltd. * License: LGPL-2.1+ The full text of the licenses can be found in the 'COPYING' file. ukui-panel-3.0.6.4/plugin-showdesktop/0000755000175000017500000000000014203402514016215 5ustar fengfengukui-panel-3.0.6.4/plugin-showdesktop/showdesktop.h0000644000175000017500000000411714203402514020743 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2011 Razor team * Authors: * Petr Vanek * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef SHOWDESKTOP_H #define SHOWDESKTOP_H #include "../panel/iukuipanelplugin.h" #include #include #include class ShowDesktop : public QWidget, public IUKUIPanelPlugin { Q_OBJECT public: ShowDesktop(const IUKUIPanelPluginStartupInfo &startupInfo); virtual QWidget *widget() { return this; } virtual QString themeId() const { return "ShowDesktop"; } void realign()override; protected: void paintEvent(QPaintEvent *); void enterEvent(QEvent *); void leaveEvent(QEvent *); void mousePressEvent(QMouseEvent *); private: enum showDeskTopState{NORMAL,HOVER}; showDeskTopState state; int xEndPoint; int yEndPoint; QTranslator *m_translator; private: void translator(); }; class ShowDesktopLibrary: public QObject, public IUKUIPanelPluginLibrary { Q_OBJECT Q_PLUGIN_METADATA(IID "ukui.org/Panel/PluginInterface/3.0") Q_INTERFACES(IUKUIPanelPluginLibrary) public: IUKUIPanelPlugin *instance(const IUKUIPanelPluginStartupInfo &startupInfo) const { return new ShowDesktop(startupInfo); } }; #endif ukui-panel-3.0.6.4/plugin-showdesktop/showdesktop.cpp0000644000175000017500000000625614203402514021304 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2011 Razor team * Authors: * Petr Vanek * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ //Qt #include #include #include #include #include //Kf5 #include #include #include //panel #include "showdesktop.h" #include "../panel/pluginsettings.h" #define DEFAULT_SHORTCUT "Control+Alt+D" #define DESKTOP_WIDTH (12) #define DESKTOP_WIDGET_HIGHT 100 ShowDesktop::ShowDesktop(const IUKUIPanelPluginStartupInfo &startupInfo) : QWidget(), IUKUIPanelPlugin(startupInfo) { translator(); state=NORMAL; this->setToolTip(tr("Show Desktop")); realign(); } void ShowDesktop::translator(){ m_translator = new QTranslator(this); QString locale = QLocale::system().name(); if (locale == "zh_CN"){ if (m_translator->load(QM_INSTALL)) qApp->installTranslator(m_translator); else qDebug() <isHorizontal()) { this->setFixedSize(DESKTOP_WIDTH,panel()->panelSize()); xEndPoint=0; yEndPoint=100; } else { this->setFixedSize(panel()->panelSize(),DESKTOP_WIDTH); xEndPoint=100; yEndPoint=0; } } void ShowDesktop::mousePressEvent(QMouseEvent *) { KWindowSystem::setShowingDesktop(!KWindowSystem::showingDesktop()); } void ShowDesktop::paintEvent(QPaintEvent *) { QStyleOption opt; opt.init(this); QPainter p(this); /*设置画笔的颜色,此处画笔作用与Line,所以必须在drawLine 之前调用*/ p.setPen(QColor(0x62,0x6C,0x6E,0xcc)); switch (state) { case NORMAL: p.drawLine(0,0,xEndPoint,yEndPoint); break; case HOVER: p.setBrush(QBrush(QColor(0xff,0xff,0xff,0x0f))); p.drawLine(0,0,xEndPoint,yEndPoint); break; default: break; } p.setRenderHint(QPainter::Antialiasing); p.drawRect(opt.rect); style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); } void ShowDesktop::enterEvent(QEvent *event) { state=HOVER; update(); } void ShowDesktop::leaveEvent(QEvent *event) { state=NORMAL; update(); } #undef DEFAULT_SHORTCUT ukui-panel-3.0.6.4/plugin-showdesktop/resources/0000755000175000017500000000000014203402514020227 5ustar fengfengukui-panel-3.0.6.4/plugin-showdesktop/resources/showdesktop.desktop.in0000644000175000017500000000026414203402514024603 0ustar fengfeng[Desktop Entry] Type=Service ServiceTypes=UKUIPanel/Plugin Name=Show desktop Comment=Minimize all windows and show the desktop Icon=user-desktop #TRANSLATIONS_DIR=../translations ukui-panel-3.0.6.4/plugin-showdesktop/CMakeLists.txt0000644000175000017500000000032114203402514020751 0ustar fengfengset(PLUGIN "showdesktop") set(HEADERS showdesktop.h ) set(SOURCES showdesktop.cpp ) include(../cmake/UkuiPluginTranslationTs.cmake) ukui_plugin_translate_ts(${PLUGIN}) BUILD_UKUI_PLUGIN(${PLUGIN}) ukui-panel-3.0.6.4/plugin-showdesktop/translation/0000755000175000017500000000000014203402514020553 5ustar fengfengukui-panel-3.0.6.4/plugin-showdesktop/translation/showdesktop_zh_CN.ts0000644000175000017500000000050014203402514024551 0ustar fengfeng ShowDesktop Show Desktop 显示桌面 ukui-panel-3.0.6.4/plugin-taskview/0000755000175000017500000000000014204636772015520 5ustar fengfengukui-panel-3.0.6.4/plugin-taskview/taskview.cpp0000644000175000017500000000727214204636772020071 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include #include #include #include #include "../panel/customstyle.h" #include #include #define UKUI_PANEL_SETTINGS "org.ukui.panel.settings" #define SHOW_TASKVIEW "showtaskview" TaskViewButton::TaskViewButton(){ setFocusPolicy(Qt::NoFocus); } TaskViewButton::~TaskViewButton(){ } TaskView::TaskView(const IUKUIPanelPluginStartupInfo &startupInfo) : QObject(), IUKUIPanelPlugin(startupInfo) { qDebug()<<"Plugin-Taskview :: TaskView start"; mButton =new TaskViewButton(); mButton->setStyle(new CustomStyle()); mButton->setIcon(QIcon::fromTheme("taskview",QIcon("/usr/share/ukui-panel/panel/img/taskview.svg"))); QTimer::singleShot(5000,[this] {mButton->setToolTip(tr("Show Taskview")); }); /* hide/show taskview * Monitor gsettings to set TaskViewButton size */ const QByteArray id(UKUI_PANEL_SETTINGS); if(QGSettings::isSchemaInstalled(id)) gsettings = new QGSettings(id); connect(gsettings, &QGSettings::changed, this, [=] (const QString &key){ if(key==SHOW_TASKVIEW) realign(); }); realign(); qDebug()<<"Plugin-Taskview :: TaskView end"; } TaskView::~TaskView() { } /* 隐藏任务视图按钮的逻辑是将buttton的大小设置为0*/ void TaskView::realign() { if(gsettings->get(SHOW_TASKVIEW).toBool()) mButton->setFixedSize(panel()->panelSize(),panel()->panelSize()); else mButton->setFixedSize(0,0); mButton->setIconSize(QSize(panel()->iconSize(),panel()->iconSize())); } /* 两种方式可调用任务视图 * 1.调用Dbus接口 * 2.调用二进制 */ void TaskViewButton::mousePressEvent(QMouseEvent *event) { const Qt::MouseButton b = event->button(); //调用dbus接口 #if 0 QString object = QString(getenv("DISPLAY")); object = object.trimmed().replace(":", "_").replace(".", "_").replace("-", "_"); object = "/org/ukui/WindowSwitch/display/" + object; QDBusInterface interface("org.ukui.WindowSwitch", object, "org.ukui.WindowSwitch", QDBusConnection::sessionBus()); if (!interface.isValid()) { qCritical() << QDBusConnection::sessionBus().lastError().message(); } if (Qt::LeftButton == b && interface.isValid()) { /* Call binary display task view * system("ukui-window-switch --show-workspace"); */ /*调用远程的value方法*/ QDBusReply reply = interface.call("handleWorkspace"); if (reply.isValid()) { if (!reply.value()) qWarning() << "Handle Workspace View Failed"; } else { qCritical() << "Call Dbus method failed"; } } #endif //调用命令 if (Qt::LeftButton == b){ system("ukui-window-switch --show-workspace"); } QWidget::mousePressEvent(event); } ukui-panel-3.0.6.4/plugin-taskview/taskview.h0000644000175000017500000000402014204636772017522 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include #include #include #include #include #include #include #include #include #include "../panel/iukuipanelplugin.h" #include "../panel/ukuipanel.h" #include "../panel/ukuicontrolstyle.h" class TaskViewButton:public UkuiToolButton { Q_OBJECT public: TaskViewButton(); ~TaskViewButton(); protected: void mousePressEvent(QMouseEvent* event); }; class TaskView: public QObject, public IUKUIPanelPlugin { Q_OBJECT public: TaskView(const IUKUIPanelPluginStartupInfo &startupInfo); ~TaskView(); virtual QWidget *widget() { return mButton; } virtual QString themeId() const { return QStringLiteral("taskview"); } void realign(); private: TaskViewButton *mButton; QGSettings *gsettings; }; class TaskViewLibrary: public QObject, public IUKUIPanelPluginLibrary { Q_OBJECT Q_PLUGIN_METADATA(IID "ukui.org/Panel/PluginInterface/3.0") Q_INTERFACES(IUKUIPanelPluginLibrary) public: IUKUIPanelPlugin *instance(const IUKUIPanelPluginStartupInfo &startupInfo) const { return new TaskView(startupInfo); } }; #endif ukui-panel-3.0.6.4/plugin-taskview/img/0000755000175000017500000000000014204636772016274 5ustar fengfengukui-panel-3.0.6.4/plugin-taskview/img/taskview.svg0000644000175000017500000000740714204636772020662 0ustar fengfeng32ukui-panel-3.0.6.4/plugin-taskview/resources/0000755000175000017500000000000014204636772017532 5ustar fengfengukui-panel-3.0.6.4/plugin-taskview/resources/taskview.desktop.in0000644000175000017500000000030014204636772023360 0ustar fengfeng[Desktop Entry] Type=Service ServiceTypes=UKUIPanel/Plugin Name=TaskView Comment=Get the taskview Icon=taskView #TRANSLATIONS_DIR=../translations Name=任务视图 Comment=任务视图插件 ukui-panel-3.0.6.4/plugin-taskview/CMakeLists.txt0000644000175000017500000000043414204636772020261 0ustar fengfengset(PLUGIN "taskview") set(HEADERS taskview.h ) set(SOURCES taskview.cpp ) include_directories(${_Qt5DBus_OWN_INCLUDE_DIRS}) install(FILES img/taskview.svg DESTINATION "/usr/share/ukui-panel/plugin-taskview/img" COMPONENT Runtime ) BUILD_UKUI_PLUGIN(${PLUGIN}) ukui-panel-3.0.6.4/plugin-quicklaunch/0000755000175000017500000000000014204636772016172 5ustar fengfengukui-panel-3.0.6.4/plugin-quicklaunch/ukuiquicklaunch.h0000644000175000017500000001747514204636772021566 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2012 Razor team * Authors: * Petr Vanek * Kuzma Shapran * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef UKUIQUICKLAUNCH_H #define UKUIQUICKLAUNCH_H #include "../panel/ukuipanel.h" #include #include #include #include #include "qlayout.h" #include "qlayoutitem.h" #include "qlayoutitem.h" #include "qgridlayout.h" #include #include #include #include #include #include #include #include QT_BEGIN_NAMESPACE class QByteArray; template class QList; template class QMap; class QString; class QStringList; class QVariant; QT_END_NAMESPACE class XdgDesktopFile; class QuickLaunchAction; class QDragEnterEvent; class QuickLaunchButton; class QSettings; class QLabel; namespace UKUi { class GridLayout; } /*! \brief Loader for "quick launcher" icons in the panel. \author Petr Vanek */ class UKUIQuickLaunch : public QFrame { Q_OBJECT public: UKUIQuickLaunch(IUKUIPanelPlugin *plugin, QWidget* parent = 0); ~UKUIQuickLaunch(); int indexOfButton(QuickLaunchButton* button) const; int countOfButtons() const; void realign(); //virtual QLayoutItem *takeAt(int index) = 0; void saveSettings(); void showPlaceHolder(); void pubAddButton (QuickLaunchAction *action) { addButton(action); } bool pubCheckIfExist(QString name); QString isComputerOrTrash(QString urlName); bool isDesktopFile(QString urlName); friend class FilectrlAdaptor; private: UKUi::GridLayout *mLayout; IUKUIPanelPlugin *mPlugin; QLabel *mPlaceHolder; QWidget *tmpwidget; void dragEnterEvent(QDragEnterEvent *e); void dropEvent(QDropEvent *e); QVector mVBtn; QGSettings *settings; QFileSystemWatcher *fsWatcher; QMap m_currentContentsMap; // 当前每个监控的内容目录列表 QString desktopFilePath ="/usr/share/applications/"; QString androidDesktopFilePath =QDir::homePath()+"/.local/share/applications/"; int apps_number; QToolButton *pageup; QToolButton *pagedown; int show_num = 0; int page_num = 1; int max_page; int old_page; QList blacklist; QList whitelist; QString mModel; QString SecurityConfigPath; void directoryUpdated(const QString &path); void GetMaxPage(); signals: void setsizeoftaskbarbutton(int _size); private slots: void refreshQuickLaunch(QString); void addButton(QuickLaunchAction* action); bool checkButton(QuickLaunchAction* action); void removeButton(QString filename); void switchButtons(QuickLaunchButton *button1, QuickLaunchButton *button2); /** * @brief rightClicktoDeleted * 快速启动栏右键删除函数 */ void rightClicktoDeleted(); /** * @brief buttonMoveLeft * 快速启动栏右键菜单-左移函数 */ void buttonMoveLeft(); /** * @brief buttonMoveRight * 快速启动栏右键菜单右移函数 */ void buttonMoveRight(); /** * @brief PageUp PageDown * 翻页按钮 */ void PageUp(); void PageDown(); QString readFile(const QString &filename); /** * @brief loadJsonfile * 加载json文件 */ void loadJsonfile(); public slots: /** * @brief AddToTaskbar * @param arg * @return * 添加到任务栏 */ bool AddToTaskbar(QString arg); /** * @brief RemoveFromTaskbar * 从任务栏取消固定 * @param arg * @return */ bool RemoveFromTaskbar(QString arg); /** * @brief FileDeleteFromTaskbar * 从任务栏移除文件的接口 * @param arg */ void FileDeleteFromTaskbar(QString arg); /** * @brief CheckIfExist * 检测此应用是否在任务栏上已经存在 * @param arg * @return */ bool CheckIfExist(QString arg); /** * @brief ShowTooltipText * 给输入法提供的信号,显示tooltip * @param arg * @return */ bool ShowTooltipText(QString arg); /** * @brief HideTooltipText * @param arg * @return * 弃用 */ bool HideTooltipText(QString arg); /** * @brief GetPanelPosition * 通过dbus获取任务栏的位置 * @param arg * @return */ int GetPanelPosition(QString arg); /** * @brief GetPanelSize * 通过dbus获取任务栏的高度 * @param arg * @return */ int GetPanelSize(QString arg); /** * @brief ReloadSecurityConfig GetSecurityConfigPath * 安全管控相关 */ void ReloadSecurityConfig(); QString GetSecurityConfigPath(); }; /** * @brief The FilectrlAdaptor class * 处理dbus的方法的类 */ class FilectrlAdaptor: public QDBusAbstractAdaptor { Q_OBJECT Q_CLASSINFO("D-Bus Interface", "com.ukui.panel.desktop") Q_CLASSINFO("D-Bus Introspection", "" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" "") public: FilectrlAdaptor(QObject *parent); virtual ~FilectrlAdaptor(); public: // PROPERTIES public Q_SLOTS: // METHODS bool AddToTaskbar(const QString &arg); bool CheckIfExist(const QString &arg); bool RemoveFromTaskbar(const QString &arg); bool FileDeleteFromTaskbar(const QString &arg); bool ShowTooltipText(const QString &arg); int GetPanelPosition(const QString &arg); int GetPanelSize(const QString &arg); void ReloadSecurityConfig(); QString GetSecurityConfigPath(); Q_SIGNALS: // SIGNALS signals: void addtak(int); }; #endif ukui-panel-3.0.6.4/plugin-quicklaunch/json.cpp0000644000175000017500000005371414204636772017661 0ustar fengfeng/** * QtJson - A simple class for parsing JSON data into a QVariant hierarchies and vice-versa. * Copyright (C) 2011 Eeli Reilin * * 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 3 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. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ /** * \file json.cpp */ #include #include #include "json.h" namespace QtJson { static QString dateFormat, dateTimeFormat; static bool prettySerialize = false; static QString sanitizeString(QString str); static QByteArray join(const QList &list, const QByteArray &sep); static QVariant parseValue(const QString &json, int &index, bool &success); static QVariant parseObject(const QString &json, int &index, bool &success); static QVariant parseArray(const QString &json, int &index, bool &success); static QVariant parseString(const QString &json, int &index, bool &success); static QVariant parseNumber(const QString &json, int &index); static int lastIndexOfNumber(const QString &json, int index); static void eatWhitespace(const QString &json, int &index); static int lookAhead(const QString &json, int index); static int nextToken(const QString &json, int &index); template QByteArray serializeMap(const T &map, bool &success, int _level = 0) { QByteArray newline; QByteArray tabs; QByteArray tabsFields; if (prettySerialize && !map.isEmpty()) { newline = "\n"; for (uint l=1; l<_level; l++) { tabs += " "; } tabsFields = tabs + " "; } QByteArray str = "{" + newline; QList pairs; for (typename T::const_iterator it = map.begin(), itend = map.end(); it != itend; ++it) { bool otherSuccess = true; QByteArray serializedValue = serialize(it.value(), otherSuccess, _level); if (serializedValue.isNull()) { success = false; break; } pairs << tabsFields + sanitizeString(it.key()).toUtf8() + ":" + (prettySerialize ? " " : "") + serializedValue; } str += join(pairs, "," + newline) + newline; str += tabs + "}"; return str; } void insert(QVariant &v, const QString &key, const QVariant &value); void append(QVariant &v, const QVariant &value); template void cloneMap(QVariant &json, const T &map) { for (typename T::const_iterator it = map.begin(), itend = map.end(); it != itend; ++it) { insert(json, it.key(), (*it)); } } template void cloneList(QVariant &json, const T &list) { for (typename T::const_iterator it = list.begin(), itend = list.end(); it != itend; ++it) { append(json, (*it)); } } /** * parse */ QVariant parse(const QString &json) { bool success = true; return parse(json, success); } /** * parse */ QVariant parse(const QString &json, bool &success) { success = true; // Return an empty QVariant if the JSON data is either null or empty if (!json.isNull() || !json.isEmpty()) { QString data = json; // We'll start from index 0 int index = 0; // Parse the first value QVariant value = parseValue(data, index, success); // Return the parsed value return value; } else { // Return the empty QVariant return QVariant(); } } /** * clone */ QVariant clone(const QVariant &data) { QVariant v; if (data.type() == QVariant::Map) { cloneMap(v, data.toMap()); } else if (data.type() == QVariant::Hash) { cloneMap(v, data.toHash()); } else if (data.type() == QVariant::List) { cloneList(v, data.toList()); } else if (data.type() == QVariant::StringList) { cloneList(v, data.toStringList()); } else { v = QVariant(data); } return v; } /** * insert value (map case) */ void insert(QVariant &v, const QString &key, const QVariant &value) { if (!v.canConvert()) v = QVariantMap(); QVariantMap *p = (QVariantMap *)v.data(); p->insert(key, clone(value)); } /** * append value (list case) */ void append(QVariant &v, const QVariant &value) { if (!v.canConvert()) v = QVariantList(); QVariantList *p = (QVariantList *)v.data(); p->append(value); } QByteArray serialize(const QVariant &data) { bool success = true; return serialize(data, success); } QByteArray serialize(const QVariant &data, bool &success, int _level /*= 0*/) { QByteArray newline; QByteArray tabs; QByteArray tabsFields; if (prettySerialize) { newline = "\n"; for (uint l=0; l<_level; l++) { tabs += " "; } tabsFields = tabs + " "; } QByteArray str; success = true; if (!data.isValid()) { // invalid or null? str = "null"; } else if ((data.type() == QVariant::List) || (data.type() == QVariant::StringList)) { // variant is a list? QList values; const QVariantList list = data.toList(); Q_FOREACH(const QVariant& v, list) { bool otherSuccess = true; QByteArray serializedValue = serialize(v, otherSuccess, _level+1); if (serializedValue.isNull()) { success = false; break; } values << tabsFields + serializedValue; } if (!values.isEmpty()) { str = "[" + newline + join( values, "," + newline ) + newline + tabs + "]"; } else { str = "[]"; } } else if (data.type() == QVariant::Hash) { // variant is a hash? str = serializeMap<>(data.toHash(), success, _level+1); } else if (data.type() == QVariant::Map) { // variant is a map? str = serializeMap<>(data.toMap(), success, _level+1); } else if ((data.type() == QVariant::String) || (data.type() == QVariant::ByteArray)) {// a string or a byte array? str = sanitizeString(data.toString()).toUtf8(); } else if (data.type() == QVariant::Double) { // double? double value = data.toDouble(&success); if (success) { str = QByteArray::number(value, 'g'); if (!str.contains(".") && ! str.contains("e")) { str += ".0"; } } } else if (data.type() == QVariant::Bool) { // boolean value? str = data.toBool() ? "true" : "false"; } else if (data.type() == QVariant::ULongLong) { // large unsigned number? str = QByteArray::number(data.value()); } else if (data.canConvert()) { // any signed number? str = QByteArray::number(data.value()); } else if (data.canConvert()) { //TODO: this code is never executed because all smaller types can be converted to qlonglong str = QString::number(data.value()).toUtf8(); } else if (data.type() == QVariant::DateTime) { // datetime value? str = sanitizeString(dateTimeFormat.isEmpty() ? data.toDateTime().toString() : data.toDateTime().toString(dateTimeFormat)).toUtf8(); } else if (data.type() == QVariant::Date) { // date value? str = sanitizeString(dateTimeFormat.isEmpty() ? data.toDate().toString() : data.toDate().toString(dateFormat)).toUtf8(); } else if (data.canConvert()) { // can value be converted to string? // this will catch QUrl, ... (all other types which can be converted to string) str = sanitizeString(data.toString()).toUtf8(); } else { success = false; } if (success) { return str; } return QByteArray(); } QString serializeStr(const QVariant &data) { return QString::fromUtf8(serialize(data)); } QString serializeStr(const QVariant &data, bool &success) { return QString::fromUtf8(serialize(data, success)); } /** * \enum JsonToken */ enum JsonToken { JsonTokenNone = 0, JsonTokenCurlyOpen = 1, JsonTokenCurlyClose = 2, JsonTokenSquaredOpen = 3, JsonTokenSquaredClose = 4, JsonTokenColon = 5, JsonTokenComma = 6, JsonTokenString = 7, JsonTokenNumber = 8, JsonTokenTrue = 9, JsonTokenFalse = 10, JsonTokenNull = 11 }; static QString sanitizeString(QString str) { str.replace(QLatin1String("\\"), QLatin1String("\\\\")); str.replace(QLatin1String("\""), QLatin1String("\\\"")); str.replace(QLatin1String("\b"), QLatin1String("\\b")); str.replace(QLatin1String("\f"), QLatin1String("\\f")); str.replace(QLatin1String("\n"), QLatin1String("\\n")); str.replace(QLatin1String("\r"), QLatin1String("\\r")); str.replace(QLatin1String("\t"), QLatin1String("\\t")); return QString(QLatin1String("\"%1\"")).arg(str); } static QByteArray join(const QList &list, const QByteArray &sep) { QByteArray res; Q_FOREACH(const QByteArray &i, list) { if (!res.isEmpty()) { res += sep; } res += i; } return res; } /** * parseValue */ static QVariant parseValue(const QString &json, int &index, bool &success) { // Determine what kind of data we should parse by // checking out the upcoming token switch(lookAhead(json, index)) { case JsonTokenString: return parseString(json, index, success); case JsonTokenNumber: return parseNumber(json, index); case JsonTokenCurlyOpen: return parseObject(json, index, success); case JsonTokenSquaredOpen: return parseArray(json, index, success); case JsonTokenTrue: nextToken(json, index); return QVariant(true); case JsonTokenFalse: nextToken(json, index); return QVariant(false); case JsonTokenNull: nextToken(json, index); return QVariant(); case JsonTokenNone: break; } // If there were no tokens, flag the failure and return an empty QVariant success = false; return QVariant(); } /** * parseObject */ static QVariant parseObject(const QString &json, int &index, bool &success) { QVariantMap map; int token; // Get rid of the whitespace and increment index nextToken(json, index); // Loop through all of the key/value pairs of the object bool done = false; while (!done) { // Get the upcoming token token = lookAhead(json, index); if (token == JsonTokenNone) { success = false; return QVariantMap(); } else if (token == JsonTokenComma) { nextToken(json, index); } else if (token == JsonTokenCurlyClose) { nextToken(json, index); return map; } else { // Parse the key/value pair's name QString name = parseString(json, index, success).toString(); if (!success) { return QVariantMap(); } // Get the next token token = nextToken(json, index); // If the next token is not a colon, flag the failure // return an empty QVariant if (token != JsonTokenColon) { success = false; return QVariant(QVariantMap()); } // Parse the key/value pair's value QVariant value = parseValue(json, index, success); if (!success) { return QVariantMap(); } // Assign the value to the key in the map map[name] = value; } } // Return the map successfully return QVariant(map); } /** * parseArray */ static QVariant parseArray(const QString &json, int &index, bool &success) { QVariantList list; nextToken(json, index); bool done = false; while(!done) { int token = lookAhead(json, index); if (token == JsonTokenNone) { success = false; return QVariantList(); } else if (token == JsonTokenComma) { nextToken(json, index); } else if (token == JsonTokenSquaredClose) { nextToken(json, index); break; } else { QVariant value = parseValue(json, index, success); if (!success) { return QVariantList(); } list.push_back(value); } } return QVariant(list); } /** * parseString */ static QVariant parseString(const QString &json, int &index, bool &success) { QString s; QChar c; eatWhitespace(json, index); c = json[index++]; bool complete = false; while(!complete) { if (index == json.size()) { break; } c = json[index++]; if (c == '\"') { complete = true; break; } else if (c == '\\') { if (index == json.size()) { break; } c = json[index++]; if (c == '\"') { s.append('\"'); } else if (c == '\\') { s.append('\\'); } else if (c == '/') { s.append('/'); } else if (c == 'b') { s.append('\b'); } else if (c == 'f') { s.append('\f'); } else if (c == 'n') { s.append('\n'); } else if (c == 'r') { s.append('\r'); } else if (c == 't') { s.append('\t'); } else if (c == 'u') { int remainingLength = json.size() - index; if (remainingLength >= 4) { QString unicodeStr = json.mid(index, 4); int symbol = unicodeStr.toInt(0, 16); s.append(QChar(symbol)); index += 4; } else { break; } } } else { s.append(c); } } if (!complete) { success = false; return QVariant(); } return QVariant(s); } /** * parseNumber */ static QVariant parseNumber(const QString &json, int &index) { eatWhitespace(json, index); int lastIndex = lastIndexOfNumber(json, index); int charLength = (lastIndex - index) + 1; QString numberStr; numberStr = json.mid(index, charLength); index = lastIndex + 1; bool ok; if (numberStr.contains('.')) { return QVariant(numberStr.toDouble(NULL)); } else if (numberStr.startsWith('-')) { int i = numberStr.toInt(&ok); if (!ok) { qlonglong ll = numberStr.toLongLong(&ok); return ok ? ll : QVariant(numberStr); } return i; } else { uint u = numberStr.toUInt(&ok); if (!ok) { qulonglong ull = numberStr.toULongLong(&ok); return ok ? ull : QVariant(numberStr); } return u; } } /** * lastIndexOfNumber */ static int lastIndexOfNumber(const QString &json, int index) { int lastIndex; for(lastIndex = index; lastIndex < json.size(); lastIndex++) { if (QString("0123456789+-.eE").indexOf(json[lastIndex]) == -1) { break; } } return lastIndex -1; } /** * eatWhitespace */ static void eatWhitespace(const QString &json, int &index) { for(; index < json.size(); index++) { if (QString(" \t\n\r").indexOf(json[index]) == -1) { break; } } } /** * lookAhead */ static int lookAhead(const QString &json, int index) { int saveIndex = index; return nextToken(json, saveIndex); } /** * nextToken */ static int nextToken(const QString &json, int &index) { eatWhitespace(json, index); if (index == json.size()) { return JsonTokenNone; } QChar c = json[index]; index++; switch(c.toLatin1()) { case '{': return JsonTokenCurlyOpen; case '}': return JsonTokenCurlyClose; case '[': return JsonTokenSquaredOpen; case ']': return JsonTokenSquaredClose; case ',': return JsonTokenComma; case '"': return JsonTokenString; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '-': return JsonTokenNumber; case ':': return JsonTokenColon; } index--; // ^ WTF? int remainingLength = json.size() - index; // True if (remainingLength >= 4) { if (json[index] == 't' && json[index + 1] == 'r' && json[index + 2] == 'u' && json[index + 3] == 'e') { index += 4; return JsonTokenTrue; } } // False if (remainingLength >= 5) { if (json[index] == 'f' && json[index + 1] == 'a' && json[index + 2] == 'l' && json[index + 3] == 's' && json[index + 4] == 'e') { index += 5; return JsonTokenFalse; } } // Null if (remainingLength >= 4) { if (json[index] == 'n' && json[index + 1] == 'u' && json[index + 2] == 'l' && json[index + 3] == 'l') { index += 4; return JsonTokenNull; } } return JsonTokenNone; } void setDateTimeFormat(const QString &format) { dateTimeFormat = format; } void setDateFormat(const QString &format) { dateFormat = format; } QString getDateTimeFormat() { return dateTimeFormat; } QString getDateFormat() { return dateFormat; } void setPrettySerialize(bool enabled) { prettySerialize = enabled; } bool isPrettySerialize() { return prettySerialize; } QQueue BuilderJsonObject::created_list; BuilderJsonObject::BuilderJsonObject() { // clean objects previous "created" while (!BuilderJsonObject::created_list.isEmpty()) { delete BuilderJsonObject::created_list.dequeue(); } } BuilderJsonObject::BuilderJsonObject(JsonObject &json) { BuilderJsonObject(); obj = json; } BuilderJsonObject *BuilderJsonObject::set(const QString &key, const QVariant &value) { obj[key] = value; return this; } BuilderJsonObject *BuilderJsonObject::set(const QString &key, BuilderJsonObject *builder) { return set(key, builder->create()); } BuilderJsonObject *BuilderJsonObject::set(const QString &key, BuilderJsonArray *builder) { return set(key, builder->create()); } JsonObject BuilderJsonObject::create() { BuilderJsonObject::created_list.enqueue(this); return obj; } QQueue BuilderJsonArray::created_list; BuilderJsonArray::BuilderJsonArray() { // clean objects previous "created" while (!BuilderJsonArray::created_list.isEmpty()) { delete BuilderJsonArray::created_list.dequeue(); } } BuilderJsonArray::BuilderJsonArray(JsonArray &json) { BuilderJsonArray(); array = json; } BuilderJsonArray *BuilderJsonArray::add(const QVariant &element) { array.append(element); return this; } BuilderJsonArray *BuilderJsonArray::add(BuilderJsonObject *builder) { return add(builder->create()); } BuilderJsonArray *BuilderJsonArray::add(BuilderJsonArray *builder) { return add(builder->create()); } JsonArray BuilderJsonArray::create() { BuilderJsonArray::created_list.enqueue(this); return array; } BuilderJsonObject *objectBuilder() { return new BuilderJsonObject(); } BuilderJsonObject *objectBuilder(JsonObject &json) { return new BuilderJsonObject(json); } BuilderJsonArray *arrayBuilder() { return new BuilderJsonArray(); } BuilderJsonArray *arrayBuilder(JsonArray &json) { return new BuilderJsonArray(json); } } //end namespace ukui-panel-3.0.6.4/plugin-quicklaunch/quicklaunchaction.h0000644000175000017500000000554214204636772022056 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2011 Razor team * Authors: * Petr Vanek * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef QUICKLAUNCHACTION_H #define QUICKLAUNCHACTION_H #include class XdgDesktopFile; /*! \brief Special action representation forUKUIQuickLaunch plugin. It supports XDG desktop files or "legacy" launching of specified apps. All process management is handled internally. \author Petr Vanek */ class QuickLaunchAction : public QAction { Q_OBJECT public: /*! Constructor for "legacy" launchers. \warning The XDG way is preferred this is only for older or non-standard apps \param name a name to display in tooltip \param exec a executable with path \param icon a valid QIcon */ QuickLaunchAction(const QString & name, const QString & exec, const QString & icon, QWidget * parent); /*! Constructor for XDG desktop handlers. */ QuickLaunchAction(const XdgDesktopFile * xdg, QWidget * parent); /*! Constructor for regular files */ QuickLaunchAction(const QString & fileName, QWidget * parent); //! Returns true if the action is valid (contains all required properties). bool isValid() { return m_valid; } QHash settingsMap() { return m_settingsMap; } /*! Returns list of additional actions to present for user (in menu). * Currently there are only "Addtitional application actions" for the ActionXdg type * (the [Desktop Action %s] in .desktop files) */ QList addtitionalActions() const { return m_addtitionalActions; } QHash m_settingsMap; QIcon getIconfromAction() { return this->icon(); } public slots: void execAction(QString additionalAction = QString{}); private: enum ActionType { ActionLegacy, ActionXdg, ActionFile }; ActionType m_type; QString m_data; bool m_valid; QList m_addtitionalActions; }; #endif ukui-panel-3.0.6.4/plugin-quicklaunch/ukuiquicklaunchplugin.h0000644000175000017500000000374614204636772023001 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2013 Razor team * Authors: * Alexander Sokoloff * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef UKUIQUICKLAUNCHPLUGIN_H #define UKUIQUICKLAUNCHPLUGIN_H #include "../panel/iukuipanelplugin.h" #include class UKUIQuickLaunch; class UKUIQuickLaunchPlugin: public QObject, public IUKUIPanelPlugin { Q_OBJECT public: explicit UKUIQuickLaunchPlugin(const IUKUIPanelPluginStartupInfo &startupInfo); ~UKUIQuickLaunchPlugin(); virtual QWidget *widget(); virtual QString themeId() const { return "QuickLaunch"; } virtual Flags flags() const { return NeedsHandle; } void realign(); bool isSeparate() const { return true; } private: UKUIQuickLaunch *mWidget; }; class UKUIQuickLaunchPluginLibrary: public QObject, public IUKUIPanelPluginLibrary { Q_OBJECT // Q_PLUGIN_METADATA(IID "ukui.org/Panel/PluginInterface/3.0") Q_INTERFACES(IUKUIPanelPluginLibrary) public: IUKUIPanelPlugin *instance(const IUKUIPanelPluginStartupInfo &startupInfo) const { return new UKUIQuickLaunchPlugin(startupInfo); } }; #endif // UKUIQUICKLAUNCHPLUGIN_H ukui-panel-3.0.6.4/plugin-quicklaunch/ukuiquicklaunchplugin.cpp0000644000175000017500000000326414204636772023327 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2013 Razor team * Authors: * Alexander Sokoloff * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "ukuiquicklaunchplugin.h" #include "ukuiquicklaunch.h" UKUIQuickLaunchPlugin::UKUIQuickLaunchPlugin(const IUKUIPanelPluginStartupInfo &startupInfo): QObject(), IUKUIPanelPlugin(startupInfo), mWidget(new UKUIQuickLaunch(this)) { FilectrlAdaptor *f; f=new FilectrlAdaptor(mWidget); QDBusConnection con=QDBusConnection::sessionBus(); if(!con.registerService("com.ukui.panel.desktop") || !con.registerObject("/",mWidget)) { qDebug()<<"fail"; } } UKUIQuickLaunchPlugin::~UKUIQuickLaunchPlugin() { delete mWidget; } QWidget *UKUIQuickLaunchPlugin::widget() { return mWidget; } void UKUIQuickLaunchPlugin::realign() { mWidget->realign(); } ukui-panel-3.0.6.4/plugin-quicklaunch/quicklaunchbutton.h0000644000175000017500000000761314204636772022115 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2012 Razor team * Authors: * Petr Vanek * Kuzma Shapran * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef UKUIQUICKLAUNCHBUTTON_H #define UKUIQUICKLAUNCHBUTTON_H #include "quicklaunchaction.h" #include #include #include "../panel/customstyle.h" #include #include #include class IUKUIPanelPlugin; //class CustomStyle; #include "../panel/ukuicontrolstyle.h" class QuickLaunchButton : public QToolButton { Q_OBJECT public: QuickLaunchButton(QuickLaunchAction * act, IUKUIPanelPlugin * plugin, QWidget* parent = 0); ~QuickLaunchButton(); QHash settingsMap(); QString file_name; QString file; QString name; QString exec; static QString mimeDataFormat() { return QLatin1String("x-ukui/quicklaunch-button"); } signals: void buttonDeleted(); void switchButtons(QuickLaunchButton *from, QuickLaunchButton *to); void movedLeft(); void movedRight(); protected: //! Disable that annoying small arrow when there is a menu /** * @brief contextMenuEvent * 右键菜单选项,从customContextMenuRequested的方式 * 改为用contextMenuEvent函数处理 */ void contextMenuEvent(QContextMenuEvent*); /** * @brief enterEvent leaveEvent * @param event * leaveEvent 和 enterEvent仅仅是为了刷新按钮状态 */ void enterEvent(QEvent *event); void leaveEvent(QEvent *event); /** * 以下是拖拽相关函数 */ void dropEvent(QDropEvent *e); virtual QMimeData * mimeData(); void dragLeaveEvent(QDragLeaveEvent *e); void mousePressEvent(QMouseEvent *e); void mouseMoveEvent(QMouseEvent *e); void mouseReleaseEvent(QMouseEvent* e); void dragEnterEvent(QDragEnterEvent *e); void dragMoveEvent(QDragMoveEvent * e); private: QuickLaunchAction *mAct; IUKUIPanelPlugin * mPlugin; QAction *mDeleteAct; QAction *mMoveLeftAct; QAction *mMoveRightAct; QMenu *mMenu; QPoint mDragStart; /** * @brief The QuickLaunchStatus enum * 快速启动栏Button的状态 */ enum QuickLaunchStatus{NORMAL, HOVER, PRESS}; QuickLaunchStatus quicklanuchstatus; /** * @brief toolbuttonstyle * 弃用接口,等待删除 */ CustomStyle toolbuttonstyle; /** * @brief mgsettings * 弃用,等待删除 */ QGSettings *mgsettings; /** * @brief isComputerOrTrash * @param urlName * @return * 未使用的接口 */ QString isComputerOrTrash(QString urlName); public slots: void selfRemove(); }; /** * @brief The ButtonMimeData class * 拖拽的时候需要用到 */ class ButtonMimeData: public QMimeData { Q_OBJECT public: ButtonMimeData(): QMimeData(), mButton(0) { } QuickLaunchButton *button() const { return mButton; } void setButton(QuickLaunchButton *button) { mButton = button; } private: QuickLaunchButton *mButton; }; #endif ukui-panel-3.0.6.4/plugin-quicklaunch/ukuiquicklaunch.cpp0000644000175000017500000007451014204636772022112 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2012 Razor team * Authors: * Petr Vanek * Kuzma Shapran * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "ukuiquicklaunch.h" #include "quicklaunchbutton.h" #include "quicklaunchaction.h" #include "../panel/iukuipanelplugin.h" #include #include #include #include #include #include #include #include #include #include #include #include "../panel/common/ukuigridlayout.h" #include "../panel/pluginsettings.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "json.h" using namespace std; using QtJson::JsonObject; using QtJson::JsonArray; #define PAGEBUTTON_SMALL_SIZE 20 #define PAGEBUTTON_MEDIUM_SIZE 30 #define PAGEBUTTON_LARGE_SIZE 40 #define PANEL_SMALL_SIZE 0 #define PANEL_MEDIUM_SIZE 1 #define PANEL_LARGE_SIZE 2 # #define PANEL_SETTINGS "org.ukui.panel.settings" #define PANEL_LINES "panellines" UKUIQuickLaunch::UKUIQuickLaunch(IUKUIPanelPlugin *plugin, QWidget* parent) : QFrame(parent), mPlugin(plugin), mPlaceHolder(0) { qDebug()<<"Plugin-Quicklaunch :: UKUIQuickLaunch start"; struct passwd *pwd; pwd=getpwuid(getuid()); pwd->pw_name; SecurityConfigPath=QString("/home/")+pwd->pw_name+QString("/.config/ukui-panel-security-config.json"); setAcceptDrops(true); mVBtn.clear(); mLayout = new UKUi::GridLayout(this); setLayout(mLayout); const QByteArray id(PANEL_SETTINGS); tmpwidget = new QWidget(this); QVBoxLayout *_style = new QVBoxLayout(tmpwidget); pageup = new QToolButton(this); pagedown = new QToolButton(this); QStyle *style = new CustomStyle; pageup->setStyle(style); pagedown->setStyle(style); pageup->setText("∧"); pagedown->setText("∨"); style->deleteLater(); _style->addWidget(pageup, 0,Qt::AlignTop|Qt::AlignHCenter); _style->addWidget(pagedown,0,Qt::AlignHCenter); _style->setContentsMargins(0,1,0,10); //tmpwidget->setFixedSize(24,mPlugin->panel()->panelSize()); if(QGSettings::isSchemaInstalled(id)){ settings=new QGSettings(id); } apps_number = settings->get("quicklaunchappsnumber").toInt(); GetMaxPage(); old_page = page_num; connect(pageup,SIGNAL(clicked()),this,SLOT(PageUp())); connect(pagedown,SIGNAL(clicked()),this,SLOT(PageDown())); connect(settings, &QGSettings::changed, this, [=] (const QString &key){ if (key == "quicklaunchappsnumber") { apps_number = settings->get("quicklaunchappsnumber").toInt(); realign(); } if(key==PANEL_LINES) { realign(); mLayout->removeWidget(tmpwidget); mLayout->addWidget(tmpwidget); mLayout->removeWidget(mPlaceHolder); } }); refreshQuickLaunch("init"); QDBusConnection::sessionBus().connect(QString(), QString("/org/kylinssoclient/path"), "org.freedesktop.kylinssoclient.interface", "keyChanged", this, SLOT(refreshQuickLaunch(QString))); /*监听系统应用的目录以及安卓兼容应用的目录*/ fsWatcher=new QFileSystemWatcher(this); fsWatcher->addPath(desktopFilePath); fsWatcher->addPath(androidDesktopFilePath); directoryUpdated(desktopFilePath); directoryUpdated(androidDesktopFilePath); connect(fsWatcher,&QFileSystemWatcher::directoryChanged,[this](){ directoryUpdated(desktopFilePath); directoryUpdated(androidDesktopFilePath); }); qDebug()<<"Plugin-Quicklaunch :: UKUIQuickLaunch end"; } UKUIQuickLaunch::~UKUIQuickLaunch() { for(auto it = mVBtn.begin(); it != mVBtn.end();) { (*it)->deleteLater(); mVBtn.erase(it); } mVBtn.clear(); } void UKUIQuickLaunch::ReloadSecurityConfig(){ this->loadJsonfile(); this->refreshQuickLaunch("ukui-panel2"); } QString UKUIQuickLaunch::GetSecurityConfigPath(){ return SecurityConfigPath; } QString UKUIQuickLaunch::readFile(const QString &filename) { QFile f(filename); if (!f.open(QFile::ReadOnly)) { return QString(); } else { QTextStream in(&f); return in.readAll(); } } void UKUIQuickLaunch::loadJsonfile() { QString json = readFile(SecurityConfigPath); if (json.isEmpty()) { qFatal("Could not read JSON file!"); return ; } bool ok; JsonObject result = QtJson::parse(json, ok).toMap(); QVariant fristLayer; fristLayer=result.value("ukui-panel"); mModel=fristLayer.toMap().value("mode").toString(); QVariant blacklistLayer; blacklistLayer=fristLayer.toMap().value("blacklist"); QVariant whitelistLayer; whitelistLayer=fristLayer.toMap().value("whitelist"); if(!blacklistLayer.isNull()){ QList thirdLayer; thirdLayer=blacklistLayer.toList(); QMap fourthLayer; fourthLayer=thirdLayer.at(0).toMap(); QList fifthLayer; fifthLayer=fourthLayer.value("entries").toList(); QMap attribute; QList blackNames; for(int i=0;i thirdLayer; thirdLayer=whitelistLayer.toList(); QMap fourthLayer; fourthLayer=thirdLayer.at(0).toMap(); QList fifthLayer; fifthLayer=fourthLayer.value("entries").toList(); QMap attribute; QList whiteNames; for(int i=0;ideleteLater(); mVBtn.erase(it); } QString desktop; QString file; QString execname; QString exec; QString icon; //qsetting的方式读取写入 apps const auto apps = mPlugin->settings()->readArray("apps"); for (const QMap &app : apps) { desktop = app.value("desktop", "").toString(); if(mblacklist.contains(desktop)){ desktop.clear(); } if(mModel=="whitelist"){ if(!mwhitelist.contains(desktop)){ desktop.clear(); } } file = app.value("file", "").toString(); if (!desktop.isEmpty()) { XdgDesktopFile xdg; if (!xdg.load(desktop)) { qDebug() << "XdgDesktopFile" << desktop << "is not valid"; continue; } /* 检测desktop文件的属性,目前UKUI桌面环境不需要此进行isSuitable检测 if (!xdg.isSuitable()) { qDebug() << "XdgDesktopFile" << desktop << "is not applicable"; continue; } */ addButton(new QuickLaunchAction(&xdg, this)); } else if (! file.isEmpty()) { addButton(new QuickLaunchAction(file, this)); } else { execname = app.value("name", "").toString(); exec = app.value("exec", "").toString(); icon = app.value("icon", "").toString(); if (icon.isNull()) { qDebug() << "Icon" << icon << "is not valid (isNull). Skipped."; continue; } //addButton(new QuickLaunchAction(execname, exec, icon, this)); } } int i = 0; int counts = countOfButtons(); int shows = (counts < apps_number ? counts : apps_number); while (i != counts && shows && counts >0) { QuickLaunchButton *b = qobject_cast(mLayout->itemAt(i)->widget()); if (shows) { b->setHidden(0); --shows; } else { b->setHidden(1); } ++i; } realign(); mLayout->addWidget(tmpwidget); } void UKUIQuickLaunch::PageUp() { --page_num; if (page_num < 1) page_num = max_page; old_page = page_num; realign(); } void UKUIQuickLaunch::PageDown() { ++page_num; if (page_num > max_page) page_num = 1; old_page = page_num; realign(); } void UKUIQuickLaunch::GetMaxPage() { if (mPlugin->panel()->isHorizontal()) { int btn_cnt = countOfButtons(); max_page = (int)(btn_cnt / apps_number); if (btn_cnt % apps_number != 0) max_page += 1; } else if (mPlugin->panel()->isMaxSize()){ int btn_cnt = countOfButtons(); max_page = (int)(btn_cnt / 2); if (btn_cnt % 2 != 0) max_page += 1; } else { int btn_cnt = countOfButtons(); max_page = (int)(btn_cnt / 3); if (btn_cnt % 3 != 0) max_page += 1; } if (page_num > max_page && max_page) page_num = max_page; } int UKUIQuickLaunch::indexOfButton(QuickLaunchButton* button) const { return mLayout->indexOf(button); } /*快速启动栏上应用的数量*/ int UKUIQuickLaunch::countOfButtons() const { return mLayout->count() - 1; } /* 快速启动栏的实时调整函数, */ void UKUIQuickLaunch::realign() { GetMaxPage(); int counts = countOfButtons(); int i = 0; int loop_times = 0; mLayout->setEnabled(false); IUKUIPanel *panel = mPlugin->panel(); if (mPlaceHolder) { mLayout->setColumnCount(1); mLayout->setRowCount(1); } else { /*这里可能存在cpu占用过高的情况*/ if (panel->isHorizontal()) { i = (page_num - 1) * apps_number; loop_times = apps_number; if (counts < apps_number) loop_times = counts - i; setMaximumWidth(mPlugin->panel()->panelSize() * apps_number + 27); if(settings->get(PANEL_LINES).toInt()==1) { mLayout->setRowCount(panel->lineCount()); mLayout->setColumnCount(0); for(auto it = mVBtn.begin(); it != mVBtn.end(); it++) { (*it)->setFixedSize(mPlugin->panel()->panelSize(),mPlugin->panel()->panelSize()); (*it)->setIconSize(QSize(mPlugin->panel()->iconSize(),mPlugin->panel()->iconSize())); } } else { mLayout->setRowCount(2); mLayout->setColumnCount(0); for(auto it = mVBtn.begin(); it != mVBtn.end(); it++) { (*it)->setFixedSize(mPlugin->panel()->panelSize()/2,mPlugin->panel()->panelSize()/2); (*it)->setIconSize(QSize(mPlugin->panel()->iconSize()/2,mPlugin->panel()->iconSize()/2)); } } if (countOfButtons() <= apps_number) { tmpwidget->setHidden(1); } else { tmpwidget->setHidden(0); } } else { if (mPlugin->panel()->isMaxSize()) { i = (page_num - 1) * 2; loop_times = 2; if (counts < 2) loop_times = counts - i; setMaximumHeight(mPlugin->panel()->panelSize() * 2 + 40); } else { i = (page_num - 1) * 3; loop_times = 3; if (counts < 3) loop_times = counts - i; setMaximumHeight(mPlugin->panel()->panelSize() * 3 + 27); } if(settings->get(PANEL_LINES).toInt()==1) { mLayout->setColumnCount(panel->lineCount()); mLayout->setRowCount(0); for(auto it = mVBtn.begin(); it != mVBtn.end(); it++) { (*it)->setFixedSize(mPlugin->panel()->panelSize(),mPlugin->panel()->panelSize()); (*it)->setIconSize(QSize(mPlugin->panel()->iconSize(),mPlugin->panel()->iconSize())); } } else { mLayout->setColumnCount(2); mLayout->setRowCount(0); for(auto it = mVBtn.begin(); it != mVBtn.end(); it++) { (*it)->setFixedSize(mPlugin->panel()->panelSize()/2,mPlugin->panel()->panelSize()/2); (*it)->setIconSize(QSize(mPlugin->panel()->iconSize()/2,mPlugin->panel()->iconSize()/2)); } } if (countOfButtons() <= 3) { tmpwidget->setHidden(1); } else { tmpwidget->setHidden(0); } if (countOfButtons() > 2 && panel->isMaxSize()) tmpwidget->setHidden(0); } } mLayout->setEnabled(true); switch(mPlugin->panel()->sizeModel()) { case PANEL_SMALL_SIZE : pageup->setFixedSize(PAGEBUTTON_SMALL_SIZE, PAGEBUTTON_SMALL_SIZE); pagedown->setFixedSize(PAGEBUTTON_SMALL_SIZE, PAGEBUTTON_SMALL_SIZE); break; case PANEL_MEDIUM_SIZE : pageup->setFixedSize(PAGEBUTTON_MEDIUM_SIZE, PAGEBUTTON_MEDIUM_SIZE); pagedown->setFixedSize(PAGEBUTTON_MEDIUM_SIZE, PAGEBUTTON_MEDIUM_SIZE); break; case PANEL_LARGE_SIZE : pageup->setFixedSize(PAGEBUTTON_LARGE_SIZE, PAGEBUTTON_LARGE_SIZE); pagedown->setFixedSize(PAGEBUTTON_LARGE_SIZE, PAGEBUTTON_LARGE_SIZE); break; } for(auto it = mVBtn.begin();it != mVBtn.end();it++) { if (!i && loop_times) { (*it)->setHidden(0); --loop_times; } else { (*it)->setHidden(1); --i; } } } void UKUIQuickLaunch::addButton(QuickLaunchAction* action) { mLayout->setEnabled(false); QuickLaunchButton *btn = new QuickLaunchButton(action, mPlugin, this); btn->setArrowType(Qt::NoArrow); /*@bug * 快速启动栏右键菜单原本的样式有对于不可选项有置灰效果, * 后跟随主题框架之后置灰效果消失,可能与此属性相关 */ // btn->setMenu(Qt::InstantPopup); mVBtn.push_back(btn); mLayout->addWidget(btn); if (countOfButtons() > apps_number) btn->setHidden(1); connect(btn, SIGNAL(switchButtons(QuickLaunchButton*,QuickLaunchButton*)), this, SLOT(switchButtons(QuickLaunchButton*,QuickLaunchButton*))); connect(btn, SIGNAL(buttonDeleted()), this, SLOT(rightClicktoDeleted())); connect(btn, SIGNAL(movedLeft()), this, SLOT(buttonMoveLeft())); connect(btn, SIGNAL(movedRight()), this, SLOT(buttonMoveRight())); mLayout->removeWidget(mPlaceHolder); mPlaceHolder->deleteLater(); mPlaceHolder = NULL; mLayout->setEnabled(true); // GetMaxPage(); realign(); mLayout->removeWidget(tmpwidget); mLayout->addWidget(tmpwidget); } bool UKUIQuickLaunch::checkButton(QuickLaunchAction* action) { bool checkresult; QString strFileName; int i = 0; int counts = countOfButtons(); /* 仅仅在快速启动栏上的应用数量大于0的时候才进行判断 * 若在快速启动栏 应用数量为0的时候b->file_name为空 * 会造成任务栏的崩溃 */ if (!action) return false; strFileName = action->m_settingsMap["desktop"]; if(countOfButtons()>0){ while (i != counts) { QuickLaunchButton *b = qobject_cast(mLayout->itemAt(i)->widget()); if (b->file_name == strFileName){ checkresult=true; break; } else { checkresult=false; ++i; } } return checkresult; } else{ qDebug()<<"countOfButtons =0 "<file_name == filename) { mVBtn.erase(it); mLayout->removeWidget(b); b->deleteLater(); this->repaint(); break; } } // GetMaxPage(); realign(); if (old_page != page_num) { old_page = page_num; PageUp(); } saveSettings(); mLayout->removeWidget(tmpwidget); mLayout->addWidget(tmpwidget); mLayout->removeWidget(mPlaceHolder); } void UKUIQuickLaunch::dragEnterEvent(QDragEnterEvent *e) { // Getting URL from mainmenu... if (e->mimeData()->hasUrls()) { e->acceptProposedAction(); return; } if (e->source() && e->source()->parent() == this) { e->acceptProposedAction(); } } bool UKUIQuickLaunch::isDesktopFile(QString urlName) { return urlName.section('/', -1, -1).section('.', -1, -1) == QString("desktop"); } QString UKUIQuickLaunch::isComputerOrTrash(QString urlName) { if (!urlName.compare("computer:///")) return QString("/usr/share/applications/peony-computer.desktop"); if (!urlName.compare("trash:///")) return QString("/usr/share/applications/peony-trash.desktop"); return urlName; } void UKUIQuickLaunch::dropEvent(QDropEvent *e) { qDebug()<<"UKUIQuickLaunch::dropEvent"; const auto urls = e->mimeData()->urls().toSet(); for (const QUrl &url : urls) { XdgDesktopFile xdg; QString urlName(url.isLocalFile() ? url.toLocalFile() : url.url()); QFileInfo ur(urlName); QString fileName("/usr/share/applications/"); fileName.append(urlName.section('/', -1, -1)); fileName = isComputerOrTrash(urlName); urlName = isComputerOrTrash(urlName); if (CheckIfExist(urlName)) return; if (CheckIfExist(fileName)) return; if (isDesktopFile(urlName)) { if (ur.isSymLink()){ if (xdg.load(urlName) && xdg.isSuitable()) { if (CheckIfExist(xdg.fileName())) return; addButton(new QuickLaunchAction(&xdg, this)); } } else { if (xdg.load(fileName) && xdg.isSuitable()) { if (CheckIfExist(urlName)) return; addButton(new QuickLaunchAction(&xdg, this)); } } } else if (ur.exists() && ur.isExecutable() && !ur.isDir() || ur.isSymLink()) { if (ur.size() <= 153600) xdg.load(urlName); addButton(new QuickLaunchAction(urlName, this)); } else if (ur.exists()) { if (ur.size() <= 153600) xdg.load(urlName); addButton(new QuickLaunchAction(urlName, this)); //taskbar->pubAddButton(new QuickLaunchAction(urlName, urlName, "", this)); } else { qWarning() << "XdgDesktopFile" << urlName << "is not valid"; QMessageBox::information(this, tr("Drop Error"), tr("File/URL '%1' cannot be embedded into QuickLaunch for now").arg(urlName) ); } } saveSettings(); } // 只要任何监控的目录更新(添加、删除、重命名),就会调用。 void UKUIQuickLaunch::directoryUpdated(const QString &path) { // 比较最新的内容和保存的内容找出区别(变化) QStringList currEntryList = m_currentContentsMap[path]; const QDir dir(path); QStringList newEntryList = dir.entryList(QDir::NoDotAndDotDot | QDir::AllDirs | QDir::Files, QDir::DirsFirst); QSet newDirSet = QSet::fromList(newEntryList); QSet currentDirSet = QSet::fromList(currEntryList); // 添加了文件 QSet newFiles = newDirSet - currentDirSet; QStringList newFile = newFiles.toList(); // 文件已被移除 QSet deletedFiles = currentDirSet - newDirSet; QStringList deleteFile = deletedFiles.toList(); // 更新当前设置 m_currentContentsMap[path] = newEntryList; if (!newFile.isEmpty() && !deleteFile.isEmpty()) { // 文件/目录重命名 if ((newFile.count() == 1) && (deleteFile.count() == 1)) { // qDebug() << QString("File Renamed from %1 to %2").arg(deleteFile.first()).arg(newFile.first()); } } else { // 添加新文件/目录至Dir if (!newFile.isEmpty()) { foreach (QString file, newFile) { // 处理操作每个新文件.... } } // 从Dir中删除文件/目录 if (!deleteFile.isEmpty()) { foreach(QString file, deleteFile) { // 处理操作每个被删除的文件.... removeButton(path+file); } } } } bool UKUIQuickLaunch::AddToTaskbar(QString arg) { const auto url=QUrl(arg); QString fileName(url.isLocalFile() ? url.toLocalFile() : url.url()); QFileInfo fi(fileName); XdgDesktopFile xdg; if (CheckIfExist(fileName)) return false; if (xdg.load(fileName)) { /*This fuction returns true if the desktop file is applicable to the current environment. but I don't need this attributes now */ // if (xdg.isSuitable()) addButton(new QuickLaunchAction(&xdg, this)); } else if (fi.exists() && fi.isExecutable() && !fi.isDir()) { addButton(new QuickLaunchAction(fileName, fileName, "", this)); } else if (fi.exists()) { addButton(new QuickLaunchAction(fileName, this)); } else { qWarning() << "XdgDesktopFile" << fileName << "is not valid"; QMessageBox::information(this, tr("Drop Error"), tr("File/URL '%1' cannot be embedded into QuickLaunch for now").arg(fileName) ); } saveSettings(); return true; } /* * @need resolved bug * 为开始菜单提供检测应用是否在任务栏上面的接口 */ bool UKUIQuickLaunch::CheckIfExist(QString arg) { if(countOfButtons()>0) { const auto url=QUrl(arg); QString fileName(url.isLocalFile() ? url.toLocalFile() : url.url()); XdgDesktopFile xdg; xdg.load(fileName); bool state; QuickLaunchAction *_action = new QuickLaunchAction(&xdg, this); state=checkButton(_action); _action->deleteLater(); return state; } return false; } bool UKUIQuickLaunch::pubCheckIfExist(QString name) { for (int i = 0; i < mVBtn.size(); i++) { QString cmpName; cmpName = (!mVBtn.value(i)->file_name.isEmpty() ? mVBtn.value(i)->file_name : (!mVBtn.value(i)->file.isEmpty() ? mVBtn.value(i)->file : (!mVBtn.value(i)->name.isEmpty() ? mVBtn.value(i)->name : mVBtn.value(i)->exec))); if (cmpName.isEmpty()) return false; if (cmpName.compare(name) == 0) return true; } return false; } /*为开始菜单提供从任务栏上移除的接口*/ bool UKUIQuickLaunch::RemoveFromTaskbar(QString arg) { const auto url=QUrl(arg); QString fileName(url.isLocalFile() ? url.toLocalFile() : url.url()); //QuickLaunchAction *_action = new QuickLaunchAction(&xdg, this); removeButton(fileName); return true; } /*从任务栏上移除文件的接口*/ void UKUIQuickLaunch::FileDeleteFromTaskbar(QString file) { removeButton(file); } bool UKUIQuickLaunch::ShowTooltipText(QString arg) { QRect rect; QToolTip::showText(QCursor::pos(),arg,nullptr,rect,3600000); return true; } bool UKUIQuickLaunch::HideTooltipText(QString arg) { QToolTip::hideText(); return true; } /*获取任务栏位置的接口*/ int UKUIQuickLaunch::GetPanelPosition(QString arg) { return mPlugin->panel()->position(); } /*获取任务栏高度的接口*/ int UKUIQuickLaunch::GetPanelSize(QString arg) { return mPlugin->panel()->panelSize(); } /**/ void UKUIQuickLaunch::switchButtons(QuickLaunchButton *button1, QuickLaunchButton *button2) { if (button1 == button2) return; int n1 = mLayout->indexOf(button1); int n2 = mLayout->indexOf(button2); int l = qMin(n1, n2); int m = qMax(n1, n2); if (l == m || mLayout->animatedMoveInProgress() ) return; mLayout->moveItem(l, m, true); mLayout->moveItem(m-1, l, true); saveSettings(); } /*右键删除*/ void UKUIQuickLaunch::rightClicktoDeleted() { QuickLaunchButton *btn = qobject_cast(sender()); if (!btn) return; removeButton(btn->file_name); /*//注释showPlaceHolder的原因是在开始菜单检测快速启动栏上面固定的应用数量的时候 //countOfButtons无法获取快速启动栏上的应用为0的情况 if (mLayout->isEmpty()){ qDebug()<<"mLayout->isEmpty()"<(sender()); if (!btn) return; int index = indexOfButton(btn); if (index > 0) { mLayout->moveItem(index, index - 1); mVBtn.move(index, index - 1); saveSettings(); } } /*快速启动栏右键 右移函数*/ void UKUIQuickLaunch::buttonMoveRight() { QuickLaunchButton *btn1 = qobject_cast(sender()); if (!btn1) return; int index = indexOfButton(btn1); if (index < countOfButtons() - 1) { mLayout->moveItem(index, index + 1); mVBtn.move(index, index + 1); saveSettings(); } } /*保持设置*/ void UKUIQuickLaunch::saveSettings() { PluginSettings *settings = mPlugin->settings(); settings->remove("apps"); QList > hashList; int size = mLayout->count(); for (int j = 0; j < size; ++j) { QuickLaunchButton *b = qobject_cast(mLayout->itemAt(j)->widget()); if (!b) continue; // convert QHash to QMap QMap map; QHashIterator it(b->settingsMap()); while (it.hasNext()) { it.next(); map[it.key()] = it.value(); } hashList << map; } settings->setArray("apps", hashList); } /*在快速启动栏区域没有应用的时候显示一块空白的区域用以实现拖拽等操作 */ void UKUIQuickLaunch::showPlaceHolder() { if (!mPlaceHolder) { mPlaceHolder = new QLabel(this); mPlaceHolder->setAlignment(Qt::AlignCenter); mPlaceHolder->setObjectName("QuickLaunchPlaceHolder"); mPlaceHolder->setText(tr("Drop application\nicons here")); } mLayout->addWidget(mPlaceHolder); } /* * Implementation of adaptor class FilectrlAdaptor * 为开始菜单提供D_Bus接口 */ FilectrlAdaptor::FilectrlAdaptor(QObject *parent) : QDBusAbstractAdaptor(parent) { // constructor setAutoRelaySignals(true); } FilectrlAdaptor::~FilectrlAdaptor() { // destructor } /*添加到快速启动栏*/ bool FilectrlAdaptor::AddToTaskbar(const QString &arg) { bool out0; QMetaObject::invokeMethod(parent(), "AddToTaskbar", Q_RETURN_ARG(bool, out0), Q_ARG(QString, arg)); return out0; } /*检测是否已经存在于快速启动栏*/ bool FilectrlAdaptor::CheckIfExist(const QString &arg) { bool out0; QMetaObject::invokeMethod(parent(), "CheckIfExist", Q_RETURN_ARG(bool, out0), Q_ARG(QString, arg)); return out0; } /*从快速启动栏删除应用*/ bool FilectrlAdaptor::RemoveFromTaskbar(const QString &arg) { bool out0; QMetaObject::invokeMethod(parent(), "RemoveFromTaskbar", Q_RETURN_ARG(bool, out0), Q_ARG(QString, arg)); return out0; } /*从快速启动栏删除应用*/ bool FilectrlAdaptor::FileDeleteFromTaskbar(const QString &arg) { bool out0; QMetaObject::invokeMethod(parent(), "FileDeleteFromTaskbar", Q_RETURN_ARG(bool, out0), Q_ARG(QString, arg)); return out0; } bool FilectrlAdaptor::ShowTooltipText(const QString &arg) { bool out0; QMetaObject::invokeMethod(parent(), "ShowTooltipText", Q_RETURN_ARG(bool, out0), Q_ARG(QString, arg)); return out0; } /*获取任务栏位置*/ int FilectrlAdaptor::GetPanelPosition(const QString &arg) { int out0; QMetaObject::invokeMethod(parent(), "GetPanelPosition", Q_RETURN_ARG(int, out0), Q_ARG(QString, arg)); return out0; } /*获取任务栏高度*/ int FilectrlAdaptor::GetPanelSize(const QString &arg) { int out0; QMetaObject::invokeMethod(parent(), "GetPanelSize", Q_RETURN_ARG(int, out0), Q_ARG(QString, arg)); return out0; } void FilectrlAdaptor::ReloadSecurityConfig() { QMetaObject::invokeMethod(parent(), "ReloadSecurityConfig"); } QString FilectrlAdaptor::GetSecurityConfigPath() { QString out0; QMetaObject::invokeMethod(parent(), "GetSecurityConfigPath", Q_RETURN_ARG(QString, out0)); return out0; } ukui-panel-3.0.6.4/plugin-quicklaunch/quicklaunchbutton.cpp0000644000175000017500000002154714204636772022452 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2011 Razor team * Authors: * Petr Vanek * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "quicklaunchbutton.h" #include "ukuiquicklaunch.h" #include "../panel/iukuipanelplugin.h" #include #include #include #include #include #include #include #include #include #include #include #define MIMETYPE "x-ukui/quicklaunch-button" #define UKUI_PANEL_SETTINGS "org.ukui.panel.settings" #define PANELPOSITION "panelposition" QuickLaunchButton::QuickLaunchButton(QuickLaunchAction * act, IUKUIPanelPlugin * plugin, QWidget * parent) : QToolButton(parent), mAct(act), mPlugin(plugin) { setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); this->setStyle(new CustomStyle()); setAcceptDrops(true); /*设置快速启动栏的按键不接受焦点*/ //setFocusPolicy(Qt::NoFocus); setAutoRaise(true); quicklanuchstatus = NORMAL; setDefaultAction(mAct); mAct->setParent(this); file_name=act->m_settingsMap["desktop"]; file = act->m_settingsMap["file"]; exec = act->m_settingsMap["exec"]; name = act->m_settingsMap["name"]; repaint(); } QuickLaunchButton::~QuickLaunchButton() { //m_act->deleteLater(); } QHash QuickLaunchButton::settingsMap() { Q_ASSERT(mAct); return mAct->settingsMap(); } void QuickLaunchButton::selfRemove() { emit buttonDeleted(); } /***************************************************/ /*quicklanuchstatus的状态*/ void QuickLaunchButton::enterEvent(QEvent *) { //quicklanuchstatus =HOVER; repaint(); } /***************************************************/ void QuickLaunchButton::leaveEvent(QEvent *) { //quicklanuchstatus=NORMAL; repaint(); } /***************************************************/ void QuickLaunchButton::mousePressEvent(QMouseEvent *e) { if (e->button() == Qt::LeftButton && e->modifiers() == Qt::ControlModifier) { mDragStart = e->pos(); return; } QToolButton::mousePressEvent(e); } void QuickLaunchButton::contextMenuEvent(QContextMenuEvent *) { if(mPlugin->panel()->isHorizontal()){ mMoveLeftAct = new QAction(XdgIcon::fromTheme("go-previous"), tr("move to left"), this); mMoveRightAct = new QAction(XdgIcon::fromTheme("go-next"), tr("move to right"), this); } else{ mMoveLeftAct = new QAction(XdgIcon::fromTheme("go-previous"), tr("move to up"), this); mMoveRightAct = new QAction(XdgIcon::fromTheme("go-next"), tr("move to down"), this); } mDeleteAct = new QAction(XdgIcon::fromTheme("dialog-close"), tr("delete from quicklaunch"), this); connect(mMoveLeftAct, SIGNAL(triggered()), this, SIGNAL(movedLeft())); connect(mMoveRightAct, SIGNAL(triggered()), this, SIGNAL(movedRight())); connect(mDeleteAct, SIGNAL(triggered()), this, SLOT(selfRemove())); mMenu = new QMenu(this); mMenu->setAttribute(Qt::WA_DeleteOnClose); mMenu->addAction(mAct); mMenu->addActions(mAct->addtitionalActions()); mMenu->addSeparator(); mMenu->addAction(mMoveLeftAct); mMenu->addAction(mMoveRightAct); mMenu->addSeparator(); mMenu->addAction(mDeleteAct); UKUIQuickLaunch *panel = qobject_cast(parent()); mMoveLeftAct->setEnabled( panel && panel->indexOfButton(this) > 0); mMoveRightAct->setEnabled(panel && panel->indexOfButton(this) < panel->countOfButtons() - 1); mPlugin->willShowWindow(mMenu); mMenu->popup(mPlugin->panel()->calculatePopupWindowPos(mapToGlobal({0, 0}), mMenu->sizeHint()).topLeft()); } /** * 以下与拖拽相关 * mimeData mouseMoveEvent dragMoveEvent dragEnterEvent dropEvent */ QMimeData * QuickLaunchButton::mimeData() { ButtonMimeData *mimeData = new ButtonMimeData(); QByteArray ba; QDataStream stream(&ba,QIODevice::WriteOnly); stream<setData(mimeDataFormat(), ba); mimeData->setButton(this); return mimeData; } /***************************************************/ void QuickLaunchButton::mouseMoveEvent(QMouseEvent *e) { if (e->button() == Qt::RightButton) return; if (!(e->buttons() & Qt::LeftButton)) return; if ((e->pos() - mDragStart).manhattanLength() < QApplication::startDragDistance()) return; if (e->modifiers() == Qt::ControlModifier) { return; } QDrag *drag = new QDrag(this); QIcon ico = icon(); int size = mPlugin->panel()->iconSize(); QPixmap img = ico.pixmap(ico.actualSize({size, size})); drag->setMimeData(mimeData()); drag->setPixmap(img); switch (mPlugin->panel()->position()) { case IUKUIPanel::PositionLeft: case IUKUIPanel::PositionTop: drag->setHotSpot({0, 0}); break; case IUKUIPanel::PositionRight: case IUKUIPanel::PositionBottom: drag->setHotSpot(img.rect().bottomRight()); break; } drag->exec(); drag->deleteLater(); //QAbstractButton::mouseMoveEvent(e); } /***************************************************/ void QuickLaunchButton::dragMoveEvent(QDragMoveEvent * e) { if (e->mimeData()->hasFormat(mimeDataFormat())) e->acceptProposedAction(); // else // e->ignore(); } void QuickLaunchButton::dragLeaveEvent(QDragLeaveEvent * e) { repaint(); QToolButton::dragLeaveEvent(e); } /***************************************************/ void QuickLaunchButton::dragEnterEvent(QDragEnterEvent *e) { e->acceptProposedAction(); const ButtonMimeData *mimeData = qobject_cast(e->mimeData()); if (mimeData && mimeData->button()) emit switchButtons(mimeData->button(), this); repaint(); QToolButton::dragEnterEvent(e); } /***************************************************/ void QuickLaunchButton::mouseReleaseEvent(QMouseEvent* e) { repaint(); QToolButton::mouseReleaseEvent(e); } void QuickLaunchButton::dropEvent(QDropEvent *e) { UKUIQuickLaunch *uqk = qobject_cast(parent()); const auto urls = e->mimeData()->urls().toSet(); for (const QUrl &url : urls) { XdgDesktopFile xdg; QString urlName(url.isLocalFile() ? url.toLocalFile() : url.url()); QFileInfo ur(urlName); QString fileName("/usr/share/applications/"); fileName.append(urlName.section('/', -1, -1)); fileName = uqk->isComputerOrTrash(urlName); urlName = uqk->isComputerOrTrash(urlName); if (uqk->pubCheckIfExist(urlName)) return; if (uqk->pubCheckIfExist(fileName)) return; if (uqk->isDesktopFile(urlName)) { if (ur.isSymLink()){ if (xdg.load(urlName) && xdg.isSuitable()) { if (uqk->pubCheckIfExist(xdg.fileName())) return; uqk->pubAddButton(new QuickLaunchAction(&xdg, this)); } } else { if (xdg.load(fileName) && xdg.isSuitable()) { if (uqk->pubCheckIfExist(urlName)) return; uqk->pubAddButton(new QuickLaunchAction(&xdg, this)); } } } else if (ur.exists() && ur.isExecutable() && !ur.isDir() || ur.isSymLink()) { if (ur.size() <= 153600) xdg.load(urlName); uqk->pubAddButton(new QuickLaunchAction(urlName, this)); } else if (ur.exists()) { if (ur.size() <= 153600) { xdg.load(urlName); } uqk->pubAddButton(new QuickLaunchAction(urlName, this)); //taskbar->pubAddButton(new QuickLaunchAction(urlName, urlName, "", this)); } else { qWarning() << "XdgDesktopFile" << urlName << "is not valid"; QMessageBox::information(this, tr("Drop Error"), tr("File/URL '%1' cannot be embedded into QuickLaunch for now").arg(urlName) ); } } uqk->saveSettings(); } ukui-panel-3.0.6.4/plugin-quicklaunch/resources/0000755000175000017500000000000014204636772020204 5ustar fengfengukui-panel-3.0.6.4/plugin-quicklaunch/resources/quicklaunch.desktop.in0000644000175000017500000000026314204636772024514 0ustar fengfeng[Desktop Entry] Type=Service ServiceTypes=UKUIPanel/Plugin Name=Quick launch Comment=Easy access to your favourite applications. Icon=quickopen #TRANSLATIONS_DIR=../translations ukui-panel-3.0.6.4/plugin-quicklaunch/CMakeLists.txt0000644000175000017500000000115614204636772020735 0ustar fengfengset(PLUGIN "quicklaunch") set(HEADERS ukuiquicklaunchplugin.h ukuiquicklaunch.h quicklaunchbutton.h quicklaunchaction.h json.h # ../panel/customstyle.h ) set(SOURCES ukuiquicklaunchplugin.cpp ukuiquicklaunch.cpp quicklaunchbutton.cpp quicklaunchaction.cpp json.cpp # ../panel/customstyle.cpp ) find_package(PkgConfig) pkg_check_modules(GIOUNIX2 REQUIRED gio-unix-2.0) include_directories( ${UKUI_INCLUDE_DIRS} "${CMAKE_CURRENT_SOURCE_DIR}/../panel" ${GIOUNIX2_INCLUDE_DIRS} ) set(LIBRARIES Qt5Xdg ${GIOUNIX2_LIBRARIES} ) BUILD_UKUI_PLUGIN(${PLUGIN}) ukui-panel-3.0.6.4/plugin-quicklaunch/json.h0000644000175000017500000001626214204636772017323 0ustar fengfeng/** * QtJson - A simple class for parsing JSON data into a QVariant hierarchies and vice-versa. * Copyright (C) 2011 Eeli Reilin * * 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 3 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. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ /** * \file json.h */ #ifndef JSON_H #define JSON_H #include #include #include /** * \namespace QtJson * \brief A JSON data parser * * Json parses a JSON data into a QVariant hierarchy. */ namespace QtJson { typedef QVariantMap JsonObject; typedef QVariantList JsonArray; /** * Clone a JSON object (makes a deep copy) * * \param data The JSON object */ QVariant clone(const QVariant &data); /** * Insert value to JSON object (QVariantMap) * * \param v The JSON object * \param key The key * \param value The value */ void insert(QVariant &v, const QString &key, const QVariant &value); /** * Append value to JSON array (QVariantList) * * \param v The JSON array * \param value The value */ void append(QVariant &v, const QVariant &value); /** * Parse a JSON string * * \param json The JSON data */ QVariant parse(const QString &json); /** * Parse a JSON string * * \param json The JSON data * \param success The success of the parsing */ QVariant parse(const QString &json, bool &success); /** * This method generates a textual JSON representation * * \param data The JSON data generated by the parser. * * \return QByteArray Textual JSON representation in UTF-8 */ QByteArray serialize(const QVariant &data); /** * This method generates a textual JSON representation * * \param data The JSON data generated by the parser. * \param success The success of the serialization * * \return QByteArray Textual JSON representation in UTF-8 */ QByteArray serialize(const QVariant &data, bool &success, int _level = 0); /** * This method generates a textual JSON representation * * \param data The JSON data generated by the parser. * * \return QString Textual JSON representation */ QString serializeStr(const QVariant &data); /** * This method generates a textual JSON representation * * \param data The JSON data generated by the parser. * \param success The success of the serialization * * \return QString Textual JSON representation */ QString serializeStr(const QVariant &data, bool &success, int _level = 0); /** * This method sets date(time) format to be used for QDateTime::toString * If QString is empty, Qt::TextDate is used. * * \param format The JSON data generated by the parser. */ void setDateTimeFormat(const QString& format); void setDateFormat(const QString& format); /** * This method gets date(time) format to be used for QDateTime::toString * If QString is empty, Qt::TextDate is used. */ QString getDateTimeFormat(); QString getDateFormat(); /** * @brief setPrettySerialize enable/disabled pretty-print when serialize() a json * @param enabled */ void setPrettySerialize(bool enabled); /** * @brief isPrettySerialize check if is enabled pretty-print when serialize() a json * @return */ bool isPrettySerialize(); /** * QVariant based Json object */ class Object : public QVariant { template Object& insertKey(Object* ptr, const QString& key) { T* p = (T*)ptr->data(); if (!p->contains(key)) p->insert(key, QVariant()); return *reinterpret_cast(&p->operator[](key)); } template void removeKey(Object *ptr, const QString& key) { T* p = (T*)ptr->data(); p->remove(key); } public: Object() : QVariant() {} Object(const Object& ref) : QVariant(ref) {} Object& operator=(const QVariant& rhs) { /** It maybe more robust when running under Qt versions below 4.7 */ QObject * obj = qvariant_cast(rhs); // setValue(rhs); setValue(obj); return *this; } Object& operator[](const QString& key) { if (type() == QVariant::Map) return insertKey(this, key); else if (type() == QVariant::Hash) return insertKey(this, key); setValue(QVariantMap()); return insertKey(this, key); } const Object& operator[](const QString& key) const { return const_cast(this)->operator[](key); } void remove(const QString& key) { if (type() == QVariant::Map) removeKey(this, key); else if (type() == QVariant::Hash) removeKey(this, key); } }; class BuilderJsonArray; /** * @brief The BuilderJsonObject class */ class BuilderJsonObject { public: BuilderJsonObject(); BuilderJsonObject(JsonObject &json); BuilderJsonObject *set(const QString &key, const QVariant &value); BuilderJsonObject *set(const QString &key, BuilderJsonObject *builder); BuilderJsonObject *set(const QString &key, BuilderJsonArray *builder); JsonObject create(); private: static QQueue created_list; JsonObject obj; }; /** * @brief The BuilderJsonArray class */ class BuilderJsonArray { public: BuilderJsonArray(); BuilderJsonArray(JsonArray &json); BuilderJsonArray *add(const QVariant &element); BuilderJsonArray *add(BuilderJsonObject *builder); BuilderJsonArray *add(BuilderJsonArray *builder); JsonArray create(); private: static QQueue created_list; JsonArray array; }; /** * @brief Create a BuilderJsonObject * @return */ BuilderJsonObject *objectBuilder(); /** * @brief Create a BuilderJsonObject starting from copy of another json * @return */ BuilderJsonObject *objectBuilder(JsonObject &json); /** * @brief Create a BuilderJsonArray * @return */ BuilderJsonArray *arrayBuilder(); /** * @brief Create a BuilderJsonArray starting from copy of another json * @return */ BuilderJsonArray *arrayBuilder(JsonArray &json); } #endif //JSON_H ukui-panel-3.0.6.4/plugin-quicklaunch/quicklaunchaction.cpp0000644000175000017500000001435414204636772022412 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2011 Razor team * Authors: * Petr Vanek * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include #include "quicklaunchaction.h" #include #include #include #include #include #include #include #include #include #include "ukuiquicklaunch.h" #include #include #include /*传入参数为三个字段*/ QuickLaunchAction::QuickLaunchAction(const QString & name, const QString & exec, const QString & icon, QWidget * parent) : QAction(name, parent), m_valid(true) { m_type = ActionLegacy; m_settingsMap["name"] = name; m_settingsMap["exec"] = exec; m_settingsMap["icon"] = icon; if (icon == "" || icon.isNull()) setIcon(XdgIcon::defaultApplicationIcon()); else setIcon(QIcon(icon)); setData(exec); connect(this, &QAction::triggered, this, [this] { execAction(); }); } /*用xdg的方式解析*/ QuickLaunchAction::QuickLaunchAction(const XdgDesktopFile * xdg, QWidget * parent) : QAction(parent), m_valid(true) { m_type = ActionXdg; m_settingsMap["desktop"] = xdg->fileName(); QString title(xdg->localizedValue("Name").toString()); QIcon icon=QIcon::fromTheme(xdg->localizedValue("Icon").toString()); //add special path search /use/share/pixmaps if (icon.isNull()) { QString path = QString("/usr/share/pixmaps/%1.%2").arg(xdg->localizedValue("Icon").toString()).arg("png"); QString path_svg = QString("/usr/share/pixmaps/%1.%2").arg(xdg->localizedValue("Icon").toString()).arg("svg"); //qDebug() << "createDesktopFileThumbnail path:" <icon(); setText(title); setIcon(icon); setData(xdg->fileName()); connect(this, &QAction::triggered, this, [this] { execAction(); }); // populate the additional actions for (auto const & action : const_cast(xdg->actions())) { QAction * act = new QAction{xdg->actionIcon(action), xdg->actionName(action), this}; act->setData(action); connect(act, &QAction::triggered, [this, act] { execAction(act->data().toString()); }); m_addtitionalActions.push_back(act); } } QuickLaunchAction::QuickLaunchAction(const QString & fileName, QWidget * parent) : QAction(parent), m_valid(true) { m_type = ActionFile; setText(fileName); setData(fileName); m_settingsMap["file"] = fileName; QFileInfo fi(fileName); if (fi.isDir()) { QFileIconProvider ip; setIcon(ip.icon(fi)); } else { QMimeDatabase db; XdgMimeType mi(db.mimeTypeForFile(fi)); setIcon(mi.icon()); } connect(this, &QAction::triggered, this, [this] { execAction(); }); } /*解析Exec字段*/ void QuickLaunchAction::execAction(QString additionalAction) { UKUIQuickLaunch *uqk = qobject_cast(parent()); QString exec(data().toString()); bool showQMessage = false; switch (m_type) { case ActionLegacy: if (!QProcess::startDetached(exec)) showQMessage =true; break; case ActionXdg: { XdgDesktopFile xdg; if(xdg.load(exec)) { if (additionalAction.isEmpty()){ GDesktopAppInfo * appinfo=g_desktop_app_info_new_from_filename(xdg.fileName().toStdString().data()); if (!g_app_info_launch_uris(G_APP_INFO(appinfo),nullptr, nullptr, nullptr)) showQMessage =true; g_object_unref(appinfo); } else { if (!xdg.actionActivate(additionalAction, QStringList{})) showQMessage =true; } #if 0 } else { //xdg 的方式实现点击打开应用,可正确读取转义的字符 if (additionalAction.isEmpty()){ if (!xdg.startDetached()) showQMessage =true; } else { if (!xdg.actionActivate(additionalAction, QStringList{})) showQMessage =true; } } #endif } else showQMessage =true; } break; case ActionFile: QFileInfo fileinfo(exec); QString openfile = exec; if (fileinfo.isSymLink()) { openfile = fileinfo.symLinkTarget(); } if (fileinfo.exists()) { QDesktopServices::openUrl(QUrl::fromLocalFile(openfile)); } else { showQMessage =true; } break; } if (showQMessage) { qWarning() << "XdgDesktopFile" << exec << "is not valid"; QMessageBox::information(uqk, tr("Error Path"), tr("File/URL cannot be opened cause invalid path.") ); } } ukui-panel-3.0.6.4/plugin-segmentation/0000755000175000017500000000000014204636772016360 5ustar fengfengukui-panel-3.0.6.4/plugin-segmentation/img/0000755000175000017500000000000014204636772017134 5ustar fengfengukui-panel-3.0.6.4/plugin-segmentation/img/segmentationh.svg0000644000175000017500000000076514204636772022532 0ustar fengfeng ukui-panel-3.0.6.4/plugin-segmentation/img/segmentation.svg0000644000175000017500000000076514204636772022362 0ustar fengfeng ukui-panel-3.0.6.4/plugin-segmentation/resources/0000755000175000017500000000000014204636772020372 5ustar fengfengukui-panel-3.0.6.4/plugin-segmentation/resources/segmentation.desktop.in0000644000175000017500000000016414204636772025070 0ustar fengfeng[Desktop Entry] Type=Service ServiceTypes=UKUIPanel/Plugin Name=Segmentation Comment=Segmentation Icon=segmentation ukui-panel-3.0.6.4/plugin-segmentation/CMakeLists.txt0000644000175000017500000000042214204636772021116 0ustar fengfengset(PLUGIN "segmentation") set(HEADERS segmentation.h ) set(SOURCES segmentation.cpp ) install(FILES img/segmentation.svg img/segmentationh.svg DESTINATION "${PACKAGE_DATA_DIR}/plugin-segmentation/img" COMPONENT Runtime ) BUILD_UKUI_PLUGIN(${PLUGIN}) ukui-panel-3.0.6.4/plugin-segmentation/segmentation.h0000644000175000017500000000403514204636772021230 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include #include #include #include #include #include #include "../panel/ukuipanel.h" #include #define DEFAULT_SHORTCUT "Alt+F1" class Segmentation : public QObject, public IUKUIPanelPlugin { Q_OBJECT public: Segmentation(const IUKUIPanelPluginStartupInfo &startupInfo); ~Segmentation(); virtual QWidget *widget() { return &mButton; } virtual QString themeId() const { return QStringLiteral("segmentation"); } void realign(); virtual IUKUIPanelPlugin::Flags flags() const { return PreferRightAlignment | HaveConfigDialog ; } private: //StartMenuWidget mWidget; //QWidget mWidget; IUKUIPanelPlugin *mPlugin; QToolButton mButton; bool mCapturing; private slots: void captureMouse(); }; class StartMenuLibrary: public QObject, public IUKUIPanelPluginLibrary { Q_OBJECT Q_PLUGIN_METADATA(IID "ukui.org/Panel/PluginInterface/3.0") Q_INTERFACES(IUKUIPanelPluginLibrary) public: IUKUIPanelPlugin *instance(const IUKUIPanelPluginStartupInfo &startupInfo) const { return new Segmentation(startupInfo); } }; #endif ukui-panel-3.0.6.4/plugin-segmentation/segmentation.cpp0000644000175000017500000001123714204636772021565 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #define DESKTOP_HEIGHT (12) #define DESKTOP_WIDTH (30) Segmentation::Segmentation(const IUKUIPanelPluginStartupInfo &startupInfo) : QObject(), IUKUIPanelPlugin(startupInfo) { mButton.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); mButton.setAutoRaise(true); realign(); mCapturing = false; // connect(&mButton, SIGNAL(clicked()), this, SLOT(captureMouse())); // mButton.setFixedSize(DESKTOP_HEIGHT,DESKTOP_WIDTH); // mButton.setStyleSheet( // //正常状态样式 // "QToolButton{" // /*"background-color:rgba(100,225,100,80%);"//背景色(也可以设置图片)*/ // "qproperty-icon:url(/usr/share/ukui-panel/plugin-segmentation/img/segmentation.svg);" // "qproperty-iconSize:40px 40px;" // "border-style:outset;" //边框样式(inset/outset) // "border-width:0px;" //边框宽度像素 // "border-radius:0px;" //边框圆角半径像素 // "border-color:rgba(255,255,255,30);" //边框颜色 // "font:SimSun 14px;" //字体,字体大小 // "color:rgba(0,0,0,100);" //字体颜色 // "padding:0px;" //填衬 // "border-bottom-style:solid" // "}" // ); } Segmentation::~Segmentation() { } void Segmentation::realign() { if(panel()->isHorizontal()) { mButton.setFixedSize(DESKTOP_HEIGHT,DESKTOP_WIDTH); mButton.setStyleSheet( //正常状态样式 "QToolButton{" /*"background-color:rgba(100,225,100,80%);"//背景色(也可以设置图片)*/ "qproperty-icon:url(/usr/share/ukui-panel/plugin-segmentation/img/segmentation.svg);" "qproperty-iconSize:40px 40px;" "border-style:outset;" //边框样式(inset/outset) "border-width:0px;" //边框宽度像素 "border-radius:0px;" //边框圆角半径像素 "border-color:rgba(255,255,255,30);" //边框颜色 "font:SimSun 14px;" //字体,字体大小 "color:rgba(0,0,0,100);" //字体颜色 "padding:0px;" //填衬 "border-bottom-style:solid" "}" ); } else { mButton.setFixedSize(DESKTOP_WIDTH,DESKTOP_HEIGHT); mButton.setStyleSheet( //正常状态样式 "QToolButton{" /*"background-color:rgba(100,225,100,80%);"//背景色(也可以设置图片)*/ "qproperty-icon:url(/usr/share/ukui-panel/plugin-segmentation/img/segmentationh.svg);" "qproperty-iconSize:40px 40px;" "border-style:outset;" //边框样式(inset/outset) "border-width:0px;" //边框宽度像素 "border-radius:0px;" //边框圆角半径像素 "border-color:rgba(255,255,255,30);" //边框颜色 "font:SimSun 14px;" //字体,字体大小 "color:rgba(0,0,0,100);" //字体颜色 "padding:0px;" //填衬 "border-bottom-style:solid" "}" ); } } void Segmentation::captureMouse() { } ukui-panel-3.0.6.4/plugin-statusnotifier/0000755000175000017500000000000014203402514016726 5ustar fengfengukui-panel-3.0.6.4/plugin-statusnotifier/statusnotifierwatcher.h0000644000175000017500000000611314203402514023541 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * LXQt - a lightweight, Qt based, desktop toolset * https://lxqt.org * * Copyright: 2015 LXQt team * Authors: * Balázs Béla * Paulo Lieuthier * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef STATUSNOTIFIERWATCHER_H #define STATUSNOTIFIERWATCHER_H #include #include #include #include #include #include "dbustypes.h" #include "statusnotifierwatcher_interface.h" class StatusNotifierWatcher : public QObject, protected QDBusContext { Q_OBJECT Q_CLASSINFO("D-Bus Interface", "org.kde.StatusNotifierWatcher") Q_SCRIPTABLE Q_PROPERTY(bool IsStatusNotifierHostRegistered READ isStatusNotifierHostRegistered) Q_SCRIPTABLE Q_PROPERTY(int ProtocolVersion READ protocolVersion) Q_SCRIPTABLE Q_PROPERTY(QStringList RegisteredStatusNotifierItems READ RegisteredStatusNotifierItems) public: explicit StatusNotifierWatcher(QObject *parent = 0); ~StatusNotifierWatcher(); bool isStatusNotifierHostRegistered() { return mHosts.count() > 0; } int protocolVersion() const { return 0; } QStringList RegisteredStatusNotifierItems() const { return mServices; } void newItem(const QString &service); signals: Q_SCRIPTABLE void StatusNotifierItemRegistered(const QString &service); Q_SCRIPTABLE void StatusNotifierItemUnregistered(const QString &service); Q_SCRIPTABLE void StatusNotifierHostRegistered(); public slots: // Q_SCRIPTABLE void RegisterStatusNotifierItem(const QString &serviceOrPath); // Q_SCRIPTABLE void RegisterStatusNotifierHost(const QString &service); void serviceUnregistered(const QString &service); private: void init(); private: QStringList mServices; QStringList mHosts; QDBusServiceWatcher *mWatcher; QString m_serviceName; org::kde::StatusNotifierWatcher *m_statusNotifierWatcher; protected Q_SLOTS: void serviceChange(const QString& name, const QString& oldOwner, const QString& newOwner); void registerWatcher(const QString& service); void unregisterWatcher(const QString& service); void serviceRegistered(const QString &service); // void serviceUnregistered(const QString &service); }; #endif // STATUSNOTIFIERWATCHER_H ukui-panel-3.0.6.4/plugin-statusnotifier/statusnotifier.h0000644000175000017500000000374714203402514022175 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * LXQt - a lightweight, Qt based, desktop toolset * https://lxqt.org * * Copyright: 2015 LXQt team * Authors: * Balázs Béla * Paulo Lieuthier * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef STATUSNOTIFIER_PLUGIN_H #define STATUSNOTIFIER_PLUGIN_H #include "../panel/iukuipanelplugin.h" #include "statusnotifierwidget.h" class StatusNotifier : public QObject, public IUKUIPanelPlugin { Q_OBJECT public: StatusNotifier(const IUKUIPanelPluginStartupInfo &startupInfo); bool isSeparate() const { return true; } void realign(); QString themeId() const { return "StatusNotifier"; } virtual Flags flags() const { return SingleInstance | NeedsHandle; } QWidget *widget() { return m_widget; } private: StatusNotifierWidget *m_widget; }; class StatusNotifierLibrary : public QObject, public IUKUIPanelPluginLibrary { Q_OBJECT // Q_PLUGIN_METADATA(IID "lxqt.org/Panel/PluginInterface/3.0") Q_INTERFACES(IUKUIPanelPluginLibrary) public: IUKUIPanelPlugin *instance(const IUKUIPanelPluginStartupInfo &startupInfo) const { return new StatusNotifier(startupInfo); } }; #endif // STATUSNOTIFIER_PLUGIN_H ukui-panel-3.0.6.4/plugin-statusnotifier/statusnotifier_storagearrow.cpp0000644000175000017500000001026614203402514025321 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see setParent(parent); this->setAcceptDrops(true); this->setStyle(new CustomStyle); this->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); const QByteArray id(UKUI_PANEL_SETTINGS); if(QGSettings::isSchemaInstalled(id)){ mGsettings = new QGSettings(id); connect(mGsettings, &QGSettings::changed, this, [=] (const QString &key){ if(key == PANEL_POSITION_KEY){ mPanelPosition=mGsettings->get(PANEL_POSITION_KEY).toInt(); setArrowIcon(); } }); } QTimer::singleShot(10,this,[=](){ setArrowIcon(); }); this->setProperty("useIconHighlightEffect", 0x2); this->setContextMenuPolicy(Qt::PreventContextMenu); //不显示右键菜单并且不将事件往基类传递 } StatusNotifierStorageArrow::~StatusNotifierStorageArrow() { } void StatusNotifierStorageArrow::dropEvent(QDropEvent *event){ } void StatusNotifierStorageArrow::dragEnterEvent(QDragEnterEvent *event){ const StatusNotifierButtonMimeData *mimeData = qobject_cast(event->mimeData()); if (mimeData && mimeData->button()){ emit addButton(mimeData->button()->mId); } if(mGsettings){ mGsettings->set(SHOW_STATUSNOTIFIER_BUTTON,true); setArrowIcon(); } event->accept(); QToolButton::dragEnterEvent(event); } void StatusNotifierStorageArrow::mousePressEvent(QMouseEvent *e) { if(e->button() == Qt::LeftButton){ if(mParent->Direction){ if(mGsettings->get(SHOW_STATUSNOTIFIER_BUTTON).toBool()){ setIcon(QIcon::fromTheme("ukui-start-symbolic")); mGsettings->set(SHOW_STATUSNOTIFIER_BUTTON,false); } else{ setIcon(QIcon::fromTheme("ukui-end-symbolic")); mGsettings->set(SHOW_STATUSNOTIFIER_BUTTON,true); } } else{ if(mGsettings->get(SHOW_STATUSNOTIFIER_BUTTON).toBool()){ setIcon(QIcon::fromTheme("ukui-up-symbolic")); mGsettings->set(SHOW_STATUSNOTIFIER_BUTTON,false); } else{ setIcon(QIcon::fromTheme("ukui-down-symbolic")); mGsettings->set(SHOW_STATUSNOTIFIER_BUTTON,true); } } } } void StatusNotifierStorageArrow::setArrowIcon() { if(mParent->Direction){ if(mGsettings->get(SHOW_STATUSNOTIFIER_BUTTON).toBool()){ setIcon(QIcon::fromTheme("ukui-end-symbolic")); } else{ setIcon(QIcon::fromTheme("ukui-start-symbolic")); } }else{ if(mGsettings->get(SHOW_STATUSNOTIFIER_BUTTON).toBool()){ setIcon(QIcon::fromTheme("ukui-down-symbolic")); } else{ setIcon(QIcon::fromTheme("ukui-up-symbolic")); } } } void StatusNotifierStorageArrow::resizeEvent(QResizeEvent *event){ if (mParent->Direction) { this->setIconSize(QSize(this->width()*0.5,this->width()*0.5)); } else { this->setIconSize(QSize(this->height()*0.5,this->height()*0.5)); } QToolButton::resizeEvent(event); } void StatusNotifierStorageArrow::mouseMoveEvent(QMouseEvent *e) { QDrag *drag = new QDrag(this); drag->exec(); drag->deleteLater(); } ukui-panel-3.0.6.4/plugin-statusnotifier/statusnotifierwidget.cpp0000644000175000017500000002336114203402514023726 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * LXQt - a lightweight, Qt based, desktop toolset * https://lxqt.org * * Copyright: 2015 LXQt team * Authors: * Balázs Béla * Paulo Lieuthier * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "statusnotifierwidget.h" #include #include #include #include "../panel/iukuipanelplugin.h" #include "../panel/customstyle.h" #define UKUI_PANEL_SETTINGS "org.ukui.panel.settings" #define SHOW_STATUSNOTIFIER_BUTTON "statusnotifierbutton" StatusNotifierWidget::StatusNotifierWidget(IUKUIPanelPlugin *plugin, QWidget *parent) : QWidget(parent), mPlugin(plugin) { mWatcher = new StatusNotifierWatcher; connect(mWatcher, &StatusNotifierWatcher::StatusNotifierItemRegistered, this, &StatusNotifierWidget::itemAdded); connect(mWatcher, &StatusNotifierWatcher::StatusNotifierItemUnregistered, this, &StatusNotifierWidget::itemRemoved); mBtn = new StatusNotifierStorageArrow(this); connect(mBtn,SIGNAL(addButton(QString)),this,SLOT(btnAddButton(QString))); mLayout = new UKUi::GridLayout(this); setLayout(mLayout); mLayout->addWidget(mBtn); const QByteArray id(UKUI_PANEL_SETTINGS); if(QGSettings::isSchemaInstalled(id)) gsettings = new QGSettings(id); connect(gsettings, &QGSettings::changed, this, [=] (const QString &key){ if(key==SHOW_STATUSNOTIFIER_BUTTON){ exchangeHideAndShow(); } }); qDebug() << mWatcher->RegisteredStatusNotifierItems(); } StatusNotifierWidget::~StatusNotifierWidget() { delete mWatcher; } void StatusNotifierWidget::itemAdded(QString serviceAndPath) { int slash = serviceAndPath.indexOf('/'); QString serv = serviceAndPath.left(slash); QString path = serviceAndPath.mid(slash); StatusNotifierButton *button = new StatusNotifierButton(serv, path, mPlugin, this); button->setStyle(new CustomStyle); connect(button, SIGNAL(switchButtons(StatusNotifierButton*,StatusNotifierButton*)), this, SLOT(switchButtons(StatusNotifierButton*,StatusNotifierButton*))); //QTimer::singleShot(200,this,[=](){resetLayout();}); connect(button,&StatusNotifierButton::layoutReady,this,[=](){ if(button->mIconStatus && !button->mId.isEmpty()) { //Icon和ID都准备好后再加入布局 mServices.insert(serviceAndPath, button); mStatusNotifierButtons.append(button); resetLayout(); } }); } void StatusNotifierWidget::itemRemoved(const QString &serviceAndPath) { StatusNotifierButton *button = mServices.value(serviceAndPath, NULL); if (button) { mStatusNotifierButtons.removeOne(button); mLayout->removeWidget(button); if(m_ShowButtons.keys().contains(button->mId)){ m_ShowButtons.remove(button->mId); } if(m_HideButtons.keys().contains(button->mId)){ m_HideButtons.remove(button->mId); } mServices.remove(serviceAndPath); m_AllButtons.remove(button->mId); resetLayout(); button->deleteLater(); } } void StatusNotifierWidget::realign() { UKUi::GridLayout *layout = qobject_cast(mLayout); layout->setEnabled(false); layout->setDirection(UKUi::GridLayout::LeftToRight); IUKUIPanel *panel = mPlugin->panel(); if (panel->isHorizontal()) { layout->setRowCount(panel->lineCount()); layout->setColumnCount(0); layout->setCellFixedSize(QSize(panel->panelSize()*0.7,panel->panelSize())); } else { layout->setColumnCount(panel->lineCount()); layout->setRowCount(0); layout->setCellFixedSize(QSize(panel->panelSize(),panel->panelSize()*0.7)); } Direction=panel->isHorizontal(); layout->setEnabled(true); } void StatusNotifierWidget::resetLayout(){ QStringList show=readSettings().at(0); show.removeAll(""); QStringList hide=readSettings().at(1); hide.removeAll(""); for(int i=0;imId,mStatusNotifierButtons.at(i)); if((!show.contains(mStatusNotifierButtons.at(i)->mId))&&(!hide.contains(mStatusNotifierButtons.at(i)->mId))){ if(mStatusNotifierButtons.at(i)->mId==""){ continue; } hide.append(mStatusNotifierButtons.at(i)->mId); saveSettings("",mStatusNotifierButtons.at(i)->mId); continue; } } else{ qDebug()<<"mStatusNotifierButtons add error : "<setVisible(gsettings->get(SHOW_STATUSNOTIFIER_BUTTON).toBool()); mLayout->addWidget(m_AllButtons.value(hide.at(i))); m_HideButtons.insert(hide.at(i),m_AllButtons.value(hide.at(i))); } } mLayout->addWidget(mBtn); for(int i=0;iaddWidget(m_AllButtons.value(show.at(i))); m_ShowButtons.insert(show.at(i),m_AllButtons.value(show.at(i))); } } } mLayout->setEnabled(true); } void StatusNotifierWidget::switchButtons(StatusNotifierButton *button1, StatusNotifierButton *button2) { if (button1 == button2) return; int n1 = mLayout->indexOf(button1); int n2 = mLayout->indexOf(button2); int l = qMin(n1, n2); int m = qMax(n1, n2); mLayout->moveItem(l, m); mLayout->moveItem(m-1, l); if(!(m_HideButtons.keys().contains(button1->mId)&&m_HideButtons.keys().contains(button2->mId))){ m_HideButtons.remove(button1->mId); } if(!(m_ShowButtons.keys().contains(button1->mId)&&m_ShowButtons.keys().contains(button2->mId))){ m_ShowButtons.remove(button1->mId); } saveSettings(button1->mId,button2->mId); resetLayout(); } void StatusNotifierWidget::saveSettings(QString button1,QString button2){ PluginSettings *settings=mPlugin->settings(); QStringList showApp=settings->value("showApp").toStringList(); QStringList hideApp=settings->value("hideApp").toStringList(); if(button2==NULL){ if(m_HideButtons.keys().contains(button1)){ m_HideButtons.remove(button1); } if(m_ShowButtons.keys().contains(button1)){ m_ShowButtons.remove(button1); } if(m_HideButtons.keys().isEmpty()){ hideApp.append(button1); if(showApp.contains(button1)){ showApp.removeAll(button1); } } if(m_ShowButtons.keys().isEmpty()){ showApp.append(button1); if(hideApp.contains(button1)){ hideApp.removeAll(button1); } } settings->setValue("showApp",showApp); settings->setValue("hideApp",hideApp); return; } if(button1==NULL){ if(!button2.isNull()){ hideApp.append(button2); hideApp.removeAll(""); settings->setValue("hideApp",hideApp); return; } } if(showApp.contains(button1)&&showApp.contains(button2)){ int tep=showApp.indexOf(button1); showApp.replace(showApp.indexOf(button2),button1); showApp.replace(tep,button2); settings->setValue("showApp",showApp); } if(showApp.contains(button1)&&hideApp.contains(button2)){ hideApp.insert(hideApp.indexOf(button2),button1); showApp.removeAll(button1); settings->setValue("showApp",showApp); settings->setValue("hideApp",hideApp); } if(hideApp.contains(button1)&&showApp.contains(button2)){ showApp.insert(showApp.indexOf(button2),button1); hideApp.removeAll(button1); settings->setValue("showApp",showApp); settings->setValue("hideApp",hideApp); } if(hideApp.contains(button1)&&hideApp.contains(button2)){ int tep=hideApp.indexOf(button1); hideApp.replace(hideApp.indexOf(button2),button1); hideApp.replace(tep,button2); settings->setValue("hideApp",hideApp); } } QList StatusNotifierWidget::readSettings(){ PluginSettings *settings=mPlugin->settings(); QStringList showApp=settings->value("showApp").toStringList(); QStringList hideApp=settings->value("hideApp").toStringList(); QList list; list.append(showApp); list.append(hideApp); return list; } void StatusNotifierWidget::exchangeHideAndShow(){ QMap::const_iterator i; for(i=m_HideButtons.constBegin();i!=m_HideButtons.constEnd();++i){ i.value()->setVisible(gsettings->get(SHOW_STATUSNOTIFIER_BUTTON).toBool()); } } void StatusNotifierWidget::btnAddButton(QString button){ saveSettings(button,""); resetLayout(); } ukui-panel-3.0.6.4/plugin-statusnotifier/statusnotifier_storagearrow.h0000644000175000017500000000330514203402514024762 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include "statusnotifierwidget.h" #define UKUI_PANEL_SETTINGS "org.ukui.panel.settings" #define SHOW_STATUSNOTIFIER_BUTTON "statusnotifierbutton" #define PANEL_POSITION_KEY "panelposition" class StatusNotifierWidget; class StatusNotifierStorageArrow : public QToolButton { Q_OBJECT public: StatusNotifierStorageArrow(StatusNotifierWidget *parent = nullptr); ~StatusNotifierStorageArrow(); protected: void mousePressEvent(QMouseEvent *e); void mouseMoveEvent(QMouseEvent *e); void dropEvent(QDropEvent *event); void dragEnterEvent(QDragEnterEvent *event); void resizeEvent(QResizeEvent *event); private: void setArrowIcon(); private: QGSettings *mGsettings; StatusNotifierWidget *mParent; int mPanelPosition; signals: void addButton(QString button); }; #endif // STATUSNOTIFIERSTORAGEARROW_H ukui-panel-3.0.6.4/plugin-statusnotifier/statusnotifieriteminterface.h0000644000175000017500000001373414203402514024732 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * LXQt - a lightweight, Qt based, desktop toolset * https://lxqt.org * * Copyright: 2015 LXQt team * Authors: * Balázs Béla * Paulo Lieuthier * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ /* * This file was generated by qdbusxml2cpp version 0.8 * Command line was: qdbusxml2cpp -c StatusNotifierItemInterface -p statusnotifieriteminterface -i dbustypes.h dbus-ifaces/org.kde.StatusNotifierItem.xml * * qdbusxml2cpp is Copyright (C) 2015 The Qt Company Ltd. * * This is an auto-generated file. * Do not edit! All changes made to it will be lost. */ #ifndef STATUSNOTIFIERITEMINTERFACE_H #define STATUSNOTIFIERITEMINTERFACE_H #include #include #include #include #include #include #include #include #include "dbustypes.h" /* * Proxy class for interface org.kde.StatusNotifierItem */ class StatusNotifierItemInterface: public QDBusAbstractInterface { Q_OBJECT public: static inline const char *staticInterfaceName() { return "org.kde.StatusNotifierItem"; } public: StatusNotifierItemInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0); ~StatusNotifierItemInterface(); Q_PROPERTY(QString AttentionIconName READ attentionIconName) inline QString attentionIconName() const { return qvariant_cast< QString >(property("AttentionIconName")); } Q_PROPERTY(IconPixmapList AttentionIconPixmap READ attentionIconPixmap) inline IconPixmapList attentionIconPixmap() const { return qvariant_cast< IconPixmapList >(property("AttentionIconPixmap")); } Q_PROPERTY(QString AttentionMovieName READ attentionMovieName) inline QString attentionMovieName() const { return qvariant_cast< QString >(property("AttentionMovieName")); } Q_PROPERTY(QString Category READ category) inline QString category() const { return qvariant_cast< QString >(property("Category")); } Q_PROPERTY(QString IconName READ iconName) inline QString iconName() const { return qvariant_cast< QString >(property("IconName")); } Q_PROPERTY(IconPixmapList IconPixmap READ iconPixmap) inline IconPixmapList iconPixmap() const { return qvariant_cast< IconPixmapList >(property("IconPixmap")); } Q_PROPERTY(QString IconThemePath READ iconThemePath) inline QString iconThemePath() const { return qvariant_cast< QString >(property("IconThemePath")); } Q_PROPERTY(QString Id READ id) inline QString id() const { return qvariant_cast< QString >(property("Id")); } Q_PROPERTY(bool ItemIsMenu READ itemIsMenu) inline bool itemIsMenu() const { return qvariant_cast< bool >(property("ItemIsMenu")); } Q_PROPERTY(QDBusObjectPath Menu READ menu) inline QDBusObjectPath menu() const { return qvariant_cast< QDBusObjectPath >(property("Menu")); } Q_PROPERTY(QString OverlayIconName READ overlayIconName) inline QString overlayIconName() const { return qvariant_cast< QString >(property("OverlayIconName")); } Q_PROPERTY(IconPixmapList OverlayIconPixmap READ overlayIconPixmap) inline IconPixmapList overlayIconPixmap() const { return qvariant_cast< IconPixmapList >(property("OverlayIconPixmap")); } Q_PROPERTY(QString Status READ status) inline QString status() const { return qvariant_cast< QString >(property("Status")); } Q_PROPERTY(QString Title READ title) inline QString title() const { return qvariant_cast< QString >(property("Title")); } Q_PROPERTY(ToolTip ToolTip READ toolTip) inline ToolTip toolTip() const { return qvariant_cast< ToolTip >(property("ToolTip")); } Q_PROPERTY(int WindowId READ windowId) inline int windowId() const { return qvariant_cast< int >(property("WindowId")); } public Q_SLOTS: // METHODS inline QDBusPendingReply<> Activate(int x, int y) { QList argumentList; argumentList << QVariant::fromValue(x) << QVariant::fromValue(y); return asyncCallWithArgumentList(QLatin1String("Activate"), argumentList); } inline QDBusPendingReply<> ContextMenu(int x, int y) { QList argumentList; argumentList << QVariant::fromValue(x) << QVariant::fromValue(y); return asyncCallWithArgumentList(QLatin1String("ContextMenu"), argumentList); } inline QDBusPendingReply<> Scroll(int delta, const QString &orientation) { QList argumentList; argumentList << QVariant::fromValue(delta) << QVariant::fromValue(orientation); return asyncCallWithArgumentList(QLatin1String("Scroll"), argumentList); } inline QDBusPendingReply<> SecondaryActivate(int x, int y) { QList argumentList; argumentList << QVariant::fromValue(x) << QVariant::fromValue(y); return asyncCallWithArgumentList(QLatin1String("SecondaryActivate"), argumentList); } Q_SIGNALS: // SIGNALS void NewAttentionIcon(); void NewIcon(); void NewOverlayIcon(); void NewStatus(const QString &status); void NewTitle(); void NewToolTip(); }; namespace org { namespace kde { typedef ::StatusNotifierItemInterface StatusNotifierItem; } } #endif ukui-panel-3.0.6.4/plugin-statusnotifier/statusnotifieriteminterface.cpp0000644000175000017500000000353714203402514025265 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * LXQt - a lightweight, Qt based, desktop toolset * https://lxqt.org * * Copyright: 2015 LXQt team * Authors: * Balázs Béla * Paulo Lieuthier * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ /* * This file was generated by qdbusxml2cpp version 0.8 * Command line was: qdbusxml2cpp -c StatusNotifierItemInterface -p statusnotifieriteminterface -i dbustypes.h dbus-ifaces/org.kde.StatusNotifierItem.xml * * qdbusxml2cpp is Copyright (C) 2015 The Qt Company Ltd. * * This is an auto-generated file. * This file may have been hand-edited. Look for HAND-EDIT comments * before re-generating it. */ #include "statusnotifieriteminterface.h" /* * Implementation of interface class StatusNotifierItemInterface */ StatusNotifierItemInterface::StatusNotifierItemInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent) : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent) { } StatusNotifierItemInterface::~StatusNotifierItemInterface() { } ukui-panel-3.0.6.4/plugin-statusnotifier/statusnotifierwidget.h0000644000175000017500000000520714203402514023372 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * LXQt - a lightweight, Qt based, desktop toolset * https://lxqt.org * * Copyright: 2015 LXQt team * Authors: * Balázs Béla * Paulo Lieuthier * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef STATUSNOTIFIERWIDGET_H #define STATUSNOTIFIERWIDGET_H #include #include #include #include #include "../panel/common/ukuigridlayout.h" #include "../panel/iukuipanelplugin.h" #include "../panel/common/ukuisettings.h" #include "../panel/pluginsettings.h" #include "statusnotifierbutton.h" #include "statusnotifierwatcher.h" #include "statusnotifier_storagearrow.h" class StatusNotifierStorageArrow; class StatusNotifierWidget : public QWidget { Q_OBJECT public: StatusNotifierWidget(IUKUIPanelPlugin *plugin, QWidget *parent = 0); ~StatusNotifierWidget(); public: bool Direction; signals: public slots: void itemAdded(QString serviceAndPath); void itemRemoved(const QString &serviceAndPath); void realign(); private: UKUi::GridLayout *mLayout; IUKUIPanelPlugin *mPlugin; StatusNotifierWatcher *mWatcher; QHash mServices; QMap m_ShowButtons; QMap m_HideButtons; QMap m_AllButtons; QList mStatusNotifierButtons; StatusNotifierStorageArrow *mBtn; QGSettings *gsettings; QTimer *time; int timecount; bool mRealign; private: void saveSettings(QString button1,QString button2); QList readSettings(); void resetLayout(); void exchangeHideAndShow(); private slots: void switchButtons(StatusNotifierButton *button1, StatusNotifierButton *button2); void btnAddButton(QString button); }; #endif // STATUSNOTIFIERWIDGET_H ukui-panel-3.0.6.4/plugin-statusnotifier/dbustypes.h0000644000175000017500000000333514203402514021125 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * LXQt - a lightweight, Qt based, desktop toolset * https://lxqt.org * * Copyright: 2015 LXQt team * Authors: * Balázs Béla * Paulo Lieuthier * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include #ifndef DBUSTYPES_H #define DBUSTYPES_H struct IconPixmap { int width; int height; QByteArray bytes; }; typedef QList IconPixmapList; struct ToolTip { QString iconName; QList iconPixmap; QString title; QString description; }; QDBusArgument &operator<<(QDBusArgument &argument, const IconPixmap &icon); const QDBusArgument &operator>>(const QDBusArgument &argument, IconPixmap &icon); QDBusArgument &operator<<(QDBusArgument &argument, const ToolTip &toolTip); const QDBusArgument &operator>>(const QDBusArgument &argument, ToolTip &toolTip); Q_DECLARE_METATYPE(IconPixmap) Q_DECLARE_METATYPE(ToolTip) #endif // DBUSTYPES_H ukui-panel-3.0.6.4/plugin-statusnotifier/statusnotifierbutton.cpp0000644000175000017500000004062514203402514023760 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * LXQt - a lightweight, Qt based, desktop toolset * https://lxqt.org * * Copyright: 2015 LXQt team * Authors: * Balázs Béla * Paulo Lieuthier * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "statusnotifierbutton.h" #include #include #include #include #include #include "../panel/iukuipanelplugin.h" #include "sniasync.h" #include "../panel/customstyle.h" #include "../panel/highlight-effect.h" #include #include //#include #define MIMETYPE "ukui/UkuiTaskBar" namespace { /*! \brief specialized DBusMenuImporter to correctly create actions' icons based * on name */ class MenuImporter : public DBusMenuImporter { public: using DBusMenuImporter::DBusMenuImporter; protected: virtual QIcon iconForName(const QString & name) override { return QIcon::fromTheme(name); } }; } StatusNotifierButton::StatusNotifierButton(QString service, QString objectPath, IUKUIPanelPlugin* plugin, QWidget *parent) : QToolButton(parent), mMenu(nullptr), mStatus(Passive), mFallbackIcon(QIcon::fromTheme("application-x-executable")), mPlugin(plugin) { // setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); // setAutoRaise(true); this->setAcceptDrops(true); interface = new SniAsync(service, objectPath, QDBusConnection::sessionBus(), this); connect(interface, &SniAsync::NewIcon, this, &StatusNotifierButton::newIcon); connect(interface, &SniAsync::NewOverlayIcon, this, &StatusNotifierButton::newOverlayIcon); connect(interface, &SniAsync::NewAttentionIcon, this, &StatusNotifierButton::newAttentionIcon); connect(interface, &SniAsync::NewToolTip, this, &StatusNotifierButton::newToolTip); connect(interface, &SniAsync::NewStatus, this, &StatusNotifierButton::newStatus); hideAbleStatusNotifierButton(); connect(this,&StatusNotifierButton::paramReady,this,[=](){ if(!this->mId.isEmpty() && this->mIconStatus && !mParamInit){ emit layoutReady(); mParamInit = true; } else{ if(this->mId.isEmpty()){ if(mCount < 5) //超过5次将不再获取 hideAbleStatusNotifierButton(); mCount++; } } }); /*Menu返回值: 无菜单项返回: "/NO_DBUSMENU"; 有菜单项返回: "/MenuBar",其他; x-sni注册的返回: "" */ interface->propertyGetAsync(QLatin1String("Menu"), [this] (QDBusObjectPath path) { if(path.path() != "/NO_DBUSMENU" && !path.path().isEmpty()) { mMenu = (new MenuImporter{interface->service(), path.path(), this})->menu(); if(mMenu){ mMenu->setObjectName(QLatin1String("StatusNotifierMenu")); KWindowEffects::enableBlurBehind(mMenu->winId(), true); } } }); interface->propertyGetAsync(QLatin1String("Status"), [this] (QString status) { newStatus(status); }); interface->propertyGetAsync(QLatin1String("IconThemePath"), [this] (QString value) { mThemePath = value; //do the logic of icons after we've got the theme path refetchIcon(Active); refetchIcon(Passive); refetchIcon(NeedsAttention); }); setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); this->setProperty("useIconHighlightEffect", 0x2); newToolTip(); systemThemeChanges(); } StatusNotifierButton::~StatusNotifierButton() { delete interface; } void StatusNotifierButton::newIcon() { refetchIcon(Passive); updataItemMenu(); } void StatusNotifierButton::newOverlayIcon() { refetchIcon(Active); } void StatusNotifierButton::newAttentionIcon() { refetchIcon(NeedsAttention); } void StatusNotifierButton::refetchIcon(Status status) { QString nameProperty, pixmapProperty; if (status == Active) { nameProperty = QLatin1String("OverlayIconName"); pixmapProperty = QLatin1String("OverlayIconPixmap"); } else if (status == NeedsAttention) { nameProperty = QLatin1String("AttentionIconName"); pixmapProperty = QLatin1String("AttentionIconPixmap"); } else // status == Passive { nameProperty = QLatin1String("IconName"); pixmapProperty = QLatin1String("IconPixmap"); } interface->propertyGetAsync(nameProperty, [this, status, pixmapProperty] (QString iconName) { QIcon nextIcon; if (!iconName.isEmpty()) { if (QIcon::hasThemeIcon(iconName)) nextIcon = QIcon::fromTheme(iconName); else { QDir themeDir(mThemePath); if (themeDir.exists()) { if (themeDir.exists(iconName + ".png")) nextIcon.addFile(themeDir.filePath(iconName + ".png")); if (themeDir.cd("hicolor") || (themeDir.cd("icons") && themeDir.cd("hicolor"))) { const QStringList sizes = themeDir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot); for (const QString &dir : sizes) { const QStringList dirs = QDir(themeDir.filePath(dir)).entryList(QDir::AllDirs | QDir::NoDotAndDotDot); for (const QString &innerDir : dirs) { QString file = themeDir.absolutePath() + "/" + dir + "/" + innerDir + "/" + iconName + ".png"; if (QFile::exists(file)) nextIcon.addFile(file); } } } } } nextIcon=HighLightEffect::drawSymbolicColoredIcon(nextIcon); switch (status) { case Active: mOverlayIcon = nextIcon; break; case NeedsAttention: mAttentionIcon = nextIcon; break; case Passive: mIcon = nextIcon; break; } resetIcon(); } else { interface->propertyGetAsync(pixmapProperty, [this, status, pixmapProperty] (IconPixmapList iconPixmaps) { if (iconPixmaps.empty()) return; QIcon nextIcon; for (IconPixmap iconPixmap: iconPixmaps) { if (!iconPixmap.bytes.isNull()) { QImage image((uchar*) iconPixmap.bytes.data(), iconPixmap.width, iconPixmap.height, QImage::Format_ARGB32); const uchar *end = image.constBits() + image.byteCount(); uchar *dest = reinterpret_cast(iconPixmap.bytes.data()); for (const uchar *src = image.constBits(); src < end; src += 4, dest += 4) qToUnaligned(qToBigEndian(qFromUnaligned(src)), dest); //图标反白 QImage currentImage= getBlackThemeIcon(image); nextIcon.addPixmap(QPixmap::fromImage(currentImage)); } } switch (status) { case Active: mOverlayIcon = nextIcon; break; case NeedsAttention: mAttentionIcon = nextIcon; break; case Passive: mIcon = nextIcon; break; } resetIcon(); }); } }); } void StatusNotifierButton::newToolTip() { interface->propertyGetAsync(QLatin1String("ToolTip"), [this] (ToolTip tooltip) { QString toolTipTitle = tooltip.title; if (!toolTipTitle.isEmpty()) setToolTip(toolTipTitle); else interface->propertyGetAsync(QLatin1String("Title"), [this] (QString title) { // we should get here only in case the ToolTip.title was empty if (!title.isEmpty()) setToolTip(title); }); }); } void StatusNotifierButton::newStatus(QString status) { Status newStatus; if (status == QLatin1String("Passive")) newStatus = Passive; else if (status == QLatin1String("Active")) newStatus = Active; else newStatus = NeedsAttention; if (mStatus == newStatus) return; mStatus = newStatus; resetIcon(); } void StatusNotifierButton::contextMenuEvent(QContextMenuEvent* event) { //XXX: avoid showing of parent's context menu, we are (optionaly) providing context menu on mouseReleaseEvent //QWidget::contextMenuEvent(event); } void StatusNotifierButton::mouseMoveEvent(QMouseEvent *e) { if (e->button() == Qt::RightButton) return; if (!(e->buttons() & Qt::LeftButton)) return; if ((e->pos() - mDragStart).manhattanLength() < QApplication::startDragDistance()) return; if (e->modifiers() == Qt::ControlModifier) { return; } QDrag *drag = new QDrag(this); QIcon ico = icon(); int size = mPlugin->panel()->iconSize(); QPixmap img = ico.pixmap(ico.actualSize({size, size})); drag->setMimeData(mimeData()); drag->setPixmap(img); switch (mPlugin->panel()->position()) { case IUKUIPanel::PositionLeft: case IUKUIPanel::PositionTop: drag->setHotSpot({0, 0}); break; case IUKUIPanel::PositionRight: case IUKUIPanel::PositionBottom: drag->setHotSpot(img.rect().bottomRight()); break; } drag->exec(); drag->deleteLater(); //QAbstractButton::mouseMoveEvent(e); } void StatusNotifierButton::mouseReleaseEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) interface->Activate(QCursor::pos().x(), QCursor::pos().y()); else if (event->button() == Qt::MidButton) interface->SecondaryActivate(QCursor::pos().x(), QCursor::pos().y()); else if (Qt::RightButton == event->button()) { if (mMenu) { if (!mMenu->isEmpty()){ mPlugin->willShowWindow(mMenu); mMenu->exec(mPlugin->panel()->calculatePopupWindowPos(QCursor::pos(), mMenu->sizeHint()).topLeft()); } } else interface->ContextMenu(QCursor::pos().x(), QCursor::pos().y()); } update(); QToolButton::mouseReleaseEvent(event); } void StatusNotifierButton::wheelEvent(QWheelEvent *event) { interface->Scroll(event->delta(), "vertical"); } void StatusNotifierButton::resetIcon() { if (mStatus == Active && !mOverlayIcon.isNull()) setIcon(mOverlayIcon); else if (mStatus == NeedsAttention && !mAttentionIcon.isNull()) setIcon(mAttentionIcon); else if (!mIcon.isNull()) // mStatus == Passive setIcon(mIcon); else if (!mOverlayIcon.isNull()) setIcon(mOverlayIcon); else if (!mAttentionIcon.isNull()) setIcon(mAttentionIcon); else setIcon(mFallbackIcon); mIconStatus=true; emit paramReady(); } void StatusNotifierButton::systemThemeChanges() { //主题变化 const QByteArray styleId(ORG_UKUI_STYLE); if(QGSettings::isSchemaInstalled(styleId)){ mThemeSettings = new QGSettings(styleId); connect(mThemeSettings, &QGSettings::changed, this, [=] (const QString &key){ if(key == ICON_THEME_NAME){ //主题变化任务栏主动更新图标 refetchIcon(Passive); } }); } } void StatusNotifierButton::updataItemMenu() { interface->propertyGetAsync(QLatin1String("Menu"), [this] (QDBusObjectPath path) { if(path.path() != "/NO_DBUSMENU" && !path.path().isEmpty()) { mMenu = (new MenuImporter{interface->service(), path.path(), this})->menu(); if(mMenu){ mMenu->setObjectName(QLatin1String("StatusNotifierMenu")); KWindowEffects::enableBlurBehind(mMenu->winId(), true); } } }); } void StatusNotifierButton::dragMoveEvent(QDragMoveEvent * e) { update(); // if (e->mimeData()->hasFormat(MIMETYPE)) // e->acceptProposedAction(); // else // e->ignore(); } void StatusNotifierButton::dragEnterEvent(QDragEnterEvent *e) { e->acceptProposedAction(); const StatusNotifierButtonMimeData *mimeData = qobject_cast(e->mimeData()); if (mimeData && mimeData->button()){ emit switchButtons(mimeData->button(), this); emit sendTitle(mimeData->button()->hideAbleStatusNotifierButton()); } QToolButton::dragEnterEvent(e); } void StatusNotifierButton::dragLeaveEvent(QDragLeaveEvent *e) { update(); //拖拽离开wigget时,需要updata e->accept(); } QMimeData * StatusNotifierButton::mimeData() { StatusNotifierButtonMimeData *mimeData = new StatusNotifierButtonMimeData(); // QByteArray ba; // mimeData->setData(mimeDataFormat(), ba); mimeData->setButton(this); return mimeData; } void StatusNotifierButton::mousePressEvent(QMouseEvent *e) { if (e->button() == Qt::LeftButton ) { mDragStart = e->pos(); return; } QToolButton::mousePressEvent(e); } bool StatusNotifierButton::event(QEvent *e) { // if(e->type() != QEvent::ToolTipChange && e->type()!=QEvent::HoverMove && e->type()!=QEvent::Paint && // e->type() != QEvent::HoverLeave && e->type()!=QEvent::Paint &&e->type() != QEvent::DragMove && // e->type() != QEvent::Leave && e->type()!=QEvent::Enter &&e->type() != QEvent::DragMove && // e->type() != QEvent::Gesture && e->type() != QEvent::MouseButtonPress && e->type() != QEvent::MouseButtonRelease && // e->type() != QEvent::GestureOverride && e->type() !=QEvent::HoverEnter && e->type() != QEvent::MouseMove && // e->type() !=QEvent::ChildAdded && e->type() != QEvent::DragEnter ) // qDebug()<type(); if(e->type() == QEvent::ChildRemoved) { emit cleansignal(); } return QToolButton::event(e); } void StatusNotifierButton::resizeEvent(QResizeEvent *event){ IUKUIPanel *panel = mPlugin->panel(); if (panel->isHorizontal()) { this->setIconSize(QSize(this->width()*0.5,this->width()*0.5)); } else { this->setIconSize(QSize(this->height()*0.5,this->height()*0.5)); } QToolButton::resizeEvent(event); } QString StatusNotifierButton::hideAbleStatusNotifierButton() { interface->propertyGetAsync(QLatin1String("Id"), [this] (QString title) { mId = ""; mId = title; emit paramReady(); }); return mId; } QImage StatusNotifierButton::getBlackThemeIcon(QImage image) { QColor standard (31,32,34); for (int x = 0; x < image.width(); x++) { for (int y = 0; y < image.height(); y++) { auto color = image.pixelColor(x, y); if (color.alpha() > 0) { if(qAbs(color.red()-standard.red())<20 && qAbs(color.green()-standard.green())<20 && qAbs(color.blue()-standard.blue())<20){ color.setRed(255); color.setGreen(255); color.setBlue(255); image.setPixelColor(x, y, color); } else{ image.setPixelColor(x, y, color); } } } } return image; } ukui-panel-3.0.6.4/plugin-statusnotifier/statusnotifierwatcher_interface.cpp0000644000175000017500000000161214203402514026113 0ustar fengfeng/* * This file was generated by qdbusxml2cpp version 0.8 * Command line was: qdbusxml2cpp -m -c OrgKdeStatusNotifierWatcherInterface -i systemtraytypedefs.h -p statusnotifierwatcher_interface kf5_org.kde.StatusNotifierWatcher.xml * * qdbusxml2cpp is Copyright (C) 2020 The Qt Company Ltd. * * This is an auto-generated file. * This file may have been hand-edited. Look for HAND-EDIT comments * before re-generating it. */ #include "statusnotifierwatcher_interface.h" /* * Implementation of interface class OrgKdeStatusNotifierWatcherInterface */ OrgKdeStatusNotifierWatcherInterface::OrgKdeStatusNotifierWatcherInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent) : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent) { } OrgKdeStatusNotifierWatcherInterface::~OrgKdeStatusNotifierWatcherInterface() { } ukui-panel-3.0.6.4/plugin-statusnotifier/.org.kde.StatusNotifierItem.xml.swp0000644000175000017500000003000014203402514025461 0ustar fengfengb0VIM 8.1O%[_U,-kylinkylin-QiTianM425-N000~kylin/panel/hpy/v101/ukui-panel-1/plugin-statusnotifier/org.kde.StatusNotifierItem.xml 3210#"! UtpEadAqEqj:9h1 R  t / F c   z y \ , gYX= |nmH:9yqp ukui-panel-3.0.6.4/plugin-statusnotifier/dbustypes.cpp0000644000175000017500000000454714203402514021466 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * LXQt - a lightweight, Qt based, desktop toolset * https://lxqt.org * * Copyright: 2015 LXQt team * Authors: * Balázs Béla * Paulo Lieuthier * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "dbustypes.h" #include // Marshall the IconPixmap data into a D-Bus argument QDBusArgument &operator<<(QDBusArgument &argument, const IconPixmap &icon) { argument.beginStructure(); argument << icon.width; argument << icon.height; argument << icon.bytes; argument.endStructure(); return argument; } // Retrieve the ImageStruct data from the D-Bus argument const QDBusArgument &operator>>(const QDBusArgument &argument, IconPixmap &icon) { argument.beginStructure(); argument >> icon.width; argument >> icon.height; argument >> icon.bytes; argument.endStructure(); return argument; } // Marshall the ToolTip data into a D-Bus argument QDBusArgument &operator<<(QDBusArgument &argument, const ToolTip &toolTip) { argument.beginStructure(); argument << toolTip.iconName; argument << toolTip.iconPixmap; argument << toolTip.title; argument << toolTip.description; argument.endStructure(); return argument; } // Retrieve the ToolTip data from the D-Bus argument const QDBusArgument &operator>>(const QDBusArgument &argument, ToolTip &toolTip) { argument.beginStructure(); argument >> toolTip.iconName; argument >> toolTip.iconPixmap; argument >> toolTip.title; argument >> toolTip.description; argument.endStructure(); return argument; } ukui-panel-3.0.6.4/plugin-statusnotifier/sniasync.cpp0000644000175000017500000000412614203402514021264 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * LXQt - a lightweight, Qt based, desktop toolset * https://lxqt.org * * Copyright: 2015 LXQt team * Authors: * Palo Kisa * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "sniasync.h" SniAsync::SniAsync(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent/* = 0*/) : QObject(parent) , mSni{service, path, connection} { //forward StatusNotifierItem signals connect(&mSni, &org::kde::StatusNotifierItem::NewAttentionIcon, this, &SniAsync::NewAttentionIcon); connect(&mSni, &org::kde::StatusNotifierItem::NewIcon, this, &SniAsync::NewIcon); connect(&mSni, &org::kde::StatusNotifierItem::NewOverlayIcon, this, &SniAsync::NewOverlayIcon); connect(&mSni, &org::kde::StatusNotifierItem::NewStatus, this, &SniAsync::NewStatus); connect(&mSni, &org::kde::StatusNotifierItem::NewTitle, this, &SniAsync::NewTitle); connect(&mSni, &org::kde::StatusNotifierItem::NewToolTip, this, &SniAsync::NewToolTip); } QDBusPendingReply SniAsync::asyncPropGet(QString const & property) { QDBusMessage msg = QDBusMessage::createMethodCall(mSni.service(), mSni.path(), QLatin1String("org.freedesktop.DBus.Properties"), QLatin1String("Get")); msg << mSni.interface() << property; return mSni.connection().asyncCall(msg); } ukui-panel-3.0.6.4/plugin-statusnotifier/dbusproperties.h0000644000175000017500000000451214203402514022153 0ustar fengfeng/* * This file was generated by qdbusxml2cpp version 0.8 * Command line was: qdbusxml2cpp -m -p dbusproperties org.freedesktop.DBus.Properties.xml * * qdbusxml2cpp is Copyright (C) 2020 The Qt Company Ltd. * * This is an auto-generated file. * Do not edit! All changes made to it will be lost. */ #ifndef DBUSPROPERTIES_H #define DBUSPROPERTIES_H #include #include #include #include #include #include #include #include /* * Proxy class for interface org.freedesktop.DBus.Properties */ class OrgFreedesktopDBusPropertiesInterface: public QDBusAbstractInterface { Q_OBJECT public: static inline const char *staticInterfaceName() { return "org.freedesktop.DBus.Properties"; } public: OrgFreedesktopDBusPropertiesInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr); ~OrgFreedesktopDBusPropertiesInterface(); public Q_SLOTS: // METHODS inline QDBusPendingReply Get(const QString &interface_name, const QString &property_name) { QList argumentList; argumentList << QVariant::fromValue(interface_name) << QVariant::fromValue(property_name); return asyncCallWithArgumentList(QStringLiteral("Get"), argumentList); } inline QDBusPendingReply GetAll(const QString &interface_name) { QList argumentList; argumentList << QVariant::fromValue(interface_name); return asyncCallWithArgumentList(QStringLiteral("GetAll"), argumentList); } inline QDBusPendingReply<> Set(const QString &interface_name, const QString &property_name, const QDBusVariant &value) { QList argumentList; argumentList << QVariant::fromValue(interface_name) << QVariant::fromValue(property_name) << QVariant::fromValue(value); return asyncCallWithArgumentList(QStringLiteral("Set"), argumentList); } Q_SIGNALS: // SIGNALS void PropertiesChanged(const QString &interface_name, const QVariantMap &changed_properties, const QStringList &invalidated_properties); }; namespace org { namespace freedesktop { namespace DBus { typedef ::OrgFreedesktopDBusPropertiesInterface Properties; } } } #endif ukui-panel-3.0.6.4/plugin-statusnotifier/sniasync.h0000644000175000017500000001060714203402514020732 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * LXQt - a lightweight, Qt based, desktop toolset * https://lxqt.org * * Copyright: 2015 LXQt team * Authors: * Palo Kisa * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #if !defined(SNIASYNC_H) #define SNIASYNC_H #include #include "statusnotifieriteminterface.h" template struct remove_class_type { using type = void; }; // bluff template struct remove_class_type { using type = R(ArgTypes...); }; template struct remove_class_type { using type = R(ArgTypes...); }; template class call_sig_helper { template static decltype(&L1::operator()) test(int); template static void test(...); //bluff public: using type = decltype(test(0)); }; template struct call_signature : public remove_class_type::type> {}; template struct call_signature { using type = R (ArgTypes...); }; template struct call_signature { using type = R (ArgTypes...); }; template struct call_signature { using type = R (ArgTypes...); }; template struct call_signature { using type = R(ArgTypes...); }; template struct is_valid_signature : public std::false_type {}; template struct is_valid_signature : public std::true_type {}; class SniAsync : public QObject { Q_OBJECT public: SniAsync(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0); template inline void propertyGetAsync(QString const &name, F finished) { static_assert(is_valid_signature::type>::value, "need callable (lambda, *function, callable obj) (Arg) -> void"); connect(new QDBusPendingCallWatcher{asyncPropGet(name), this}, &QDBusPendingCallWatcher::finished, [this, finished, name] (QDBusPendingCallWatcher * call) { QDBusPendingReply reply = *call; if (reply.isError()) qDebug() << "Error on DBus request:" << reply.error(); finished(qdbus_cast::type>::argument_type>(reply.value())); call->deleteLater(); } ); } //exposed methods from org::kde::StatusNotifierItem inline QString service() const { return mSni.service(); } public slots: //Forwarded slots from org::kde::StatusNotifierItem inline QDBusPendingReply<> Activate(int x, int y) { return mSni.Activate(x, y); } inline QDBusPendingReply<> ContextMenu(int x, int y) { return mSni.ContextMenu(x, y); } inline QDBusPendingReply<> Scroll(int delta, const QString &orientation) { return mSni.Scroll(delta, orientation); } inline QDBusPendingReply<> SecondaryActivate(int x, int y) { return mSni.SecondaryActivate(x, y); } signals: //Forwarded signals from org::kde::StatusNotifierItem void NewAttentionIcon(); void NewIcon(); void NewOverlayIcon(); void NewStatus(const QString &status); void NewTitle(); void NewToolTip(); private: QDBusPendingReply asyncPropGet(QString const & property); private: org::kde::StatusNotifierItem mSni; }; #endif ukui-panel-3.0.6.4/plugin-statusnotifier/resources/0000755000175000017500000000000014203402514020740 5ustar fengfengukui-panel-3.0.6.4/plugin-statusnotifier/resources/statusnotifier.desktop.in0000644000175000017500000000020514203402514026020 0ustar fengfeng[Desktop Entry] Type=Service ServiceTypes=UKUIPanel/Plugin Name=Status Notifier Plugin Comment=Status Notifier Plugin Icon=go-bottom ukui-panel-3.0.6.4/plugin-statusnotifier/CMakeLists.txt0000644000175000017500000000172414203402514021472 0ustar fengfengset(PLUGIN "statusnotifier") find_package(dbusmenu-qt5 REQUIRED) set(HEADERS statusnotifier.h dbustypes.h statusnotifierbutton.h statusnotifieriteminterface.h statusnotifierwatcher.h statusnotifierwidget.h sniasync.h statusnotifier_storagearrow.h statusnotifierwatcher_interface.h systemtraytypedefs.h dbusproperties.h ) set(SOURCES statusnotifier.cpp dbustypes.cpp statusnotifierbutton.cpp statusnotifieriteminterface.cpp statusnotifierwatcher.cpp statusnotifierwidget.cpp sniasync.cpp statusnotifier_storagearrow.cpp statusnotifierwatcher_interface.cpp dbusproperties.cpp ) qt5_add_dbus_adaptor(DBUS_SOURCES org.kde.StatusNotifierItem.xml statusnotifieriteminterface.h StatusNotifierItemInterface ) set_source_files_properties(${DBUS_SOURCES} PROPERTIES SKIP_AUTOGEN ON) list(APPEND SOURCES "${DBUS_SOURCES}") set(LIBRARIES dbusmenu-qt5 ) BUILD_UKUI_PLUGIN(${PLUGIN}) ukui-panel-3.0.6.4/plugin-statusnotifier/statusnotifier.cpp0000644000175000017500000000245014203402514022516 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * LXQt - a lightweight, Qt based, desktop toolset * https://lxqt.org * * Copyright: 2015 LXQt team * Authors: * Balázs Béla * Paulo Lieuthier * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "statusnotifier.h" StatusNotifier::StatusNotifier(const IUKUIPanelPluginStartupInfo &startupInfo) : QObject(), IUKUIPanelPlugin(startupInfo) { m_widget = new StatusNotifierWidget(this); } void StatusNotifier::realign() { m_widget->realign(); } ukui-panel-3.0.6.4/plugin-statusnotifier/systemtraytypedefs.h0000755000175000017500000000365114203402514023077 0ustar fengfeng/*************************************************************************** * * * Copyright (C) 2009 Marco Martin * * * * 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. * * * * 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 . * ***************************************************************************/ #ifndef SYSTEMTRAYTYPEDEFS_H #define SYSTEMTRAYTYPEDEFS_H #include #include #include struct KDbusImageStruct { int width; int height; QByteArray data; }; typedef QVector KDbusImageVector; struct KDbusToolTipStruct { QString icon; KDbusImageVector image; QString title; QString subTitle; }; Q_DECLARE_METATYPE(KDbusImageStruct) Q_DECLARE_METATYPE(KDbusImageVector) Q_DECLARE_METATYPE(KDbusToolTipStruct) #endif ukui-panel-3.0.6.4/plugin-statusnotifier/statusnotifierwatcher_interface.h0000644000175000017500000000532514203402514025565 0ustar fengfeng/* * This file was generated by qdbusxml2cpp version 0.8 * Command line was: qdbusxml2cpp -m -c OrgKdeStatusNotifierWatcherInterface -i systemtraytypedefs.h -p statusnotifierwatcher_interface kf5_org.kde.StatusNotifierWatcher.xml * * qdbusxml2cpp is Copyright (C) 2020 The Qt Company Ltd. * * This is an auto-generated file. * Do not edit! All changes made to it will be lost. */ #ifndef STATUSNOTIFIERWATCHER_INTERFACE_H #define STATUSNOTIFIERWATCHER_INTERFACE_H #include #include #include #include #include #include #include #include #include "systemtraytypedefs.h" /* * Proxy class for interface org.kde.StatusNotifierWatcher */ class OrgKdeStatusNotifierWatcherInterface: public QDBusAbstractInterface { Q_OBJECT public: static inline const char *staticInterfaceName() { return "org.kde.StatusNotifierWatcher"; } public: OrgKdeStatusNotifierWatcherInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr); ~OrgKdeStatusNotifierWatcherInterface(); Q_PROPERTY(bool IsStatusNotifierHostRegistered READ isStatusNotifierHostRegistered) inline bool isStatusNotifierHostRegistered() const { return qvariant_cast< bool >(property("IsStatusNotifierHostRegistered")); } Q_PROPERTY(int ProtocolVersion READ protocolVersion) inline int protocolVersion() const { return qvariant_cast< int >(property("ProtocolVersion")); } Q_PROPERTY(QStringList RegisteredStatusNotifierItems READ registeredStatusNotifierItems) inline QStringList registeredStatusNotifierItems() const { return qvariant_cast< QStringList >(property("RegisteredStatusNotifierItems")); } public Q_SLOTS: // METHODS inline QDBusPendingReply<> RegisterStatusNotifierHost(const QString &service) { QList argumentList; argumentList << QVariant::fromValue(service); return asyncCallWithArgumentList(QStringLiteral("RegisterStatusNotifierHost"), argumentList); } inline QDBusPendingReply<> RegisterStatusNotifierItem(const QString &service) { QList argumentList; argumentList << QVariant::fromValue(service); return asyncCallWithArgumentList(QStringLiteral("RegisterStatusNotifierItem"), argumentList); } Q_SIGNALS: // SIGNALS void StatusNotifierHostRegistered(); void StatusNotifierHostUnregistered(); void StatusNotifierItemRegistered(const QString &in0); void StatusNotifierItemUnregistered(const QString &in0); }; namespace org { namespace kde { typedef ::OrgKdeStatusNotifierWatcherInterface StatusNotifierWatcher; } } #endif ukui-panel-3.0.6.4/plugin-statusnotifier/org.kde.StatusNotifierItem.xml0000644000175000017500000000461714203402514024612 0ustar fengfeng ukui-panel-3.0.6.4/plugin-statusnotifier/dbusproperties.cpp0000644000175000017500000000145414203402514022510 0ustar fengfeng/* * This file was generated by qdbusxml2cpp version 0.8 * Command line was: qdbusxml2cpp -m -p dbusproperties org.freedesktop.DBus.Properties.xml * * qdbusxml2cpp is Copyright (C) 2020 The Qt Company Ltd. * * This is an auto-generated file. * This file may have been hand-edited. Look for HAND-EDIT comments * before re-generating it. */ #include "dbusproperties.h" /* * Implementation of interface class OrgFreedesktopDBusPropertiesInterface */ OrgFreedesktopDBusPropertiesInterface::OrgFreedesktopDBusPropertiesInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent) : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent) { } OrgFreedesktopDBusPropertiesInterface::~OrgFreedesktopDBusPropertiesInterface() { } ukui-panel-3.0.6.4/plugin-statusnotifier/statusnotifierbutton.h0000644000175000017500000000762614203402514023431 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * LXQt - a lightweight, Qt based, desktop toolset * https://lxqt.org * * Copyright: 2015 LXQt team * Authors: * Balázs Béla * Paulo Lieuthier * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef STATUSNOTIFIERBUTTON_H #define STATUSNOTIFIERBUTTON_H #include "../panel/iukuipanelplugin.h" #include #include #include #include #include #include #include #include #include #include #include #define ORG_UKUI_STYLE "org.ukui.style" #define ICON_THEME_NAME "iconThemeName" #if QT_VERSION < QT_VERSION_CHECK(5, 5, 0) template inline T qFromUnaligned(const uchar *src) { T dest; const size_t size = sizeof(T); memcpy(&dest, src, size); return dest; } #endif class IUKUIPanelPlugin; class SniAsync; class StatusNotifierButton : public QToolButton { Q_OBJECT public: StatusNotifierButton(QString service, QString objectPath, IUKUIPanelPlugin* plugin, QWidget *parent = 0); ~StatusNotifierButton(); enum Status { Passive, Active, NeedsAttention }; QString hideAbleStatusNotifierButton(); static QString mimeDataFormat() { return QLatin1String("x-ukui/statusnotifier-button"); } QImage getBlackThemeIcon(QImage image); public slots: void newIcon(); void newAttentionIcon(); void newOverlayIcon(); void newToolTip(); void newStatus(QString status); public: QString mId; bool mIdStatus=false; bool mIconStatus=false; private: SniAsync *interface; QMenu *mMenu; Status mStatus; QString mThemePath; QIcon mIcon, mOverlayIcon, mAttentionIcon, mFallbackIcon; QPoint mDragStart; IUKUIPanelPlugin* mPlugin; QString drag_status_flag; uint mCount = 0; bool mParamInit=false; QGSettings *mThemeSettings; signals: void switchButtons(StatusNotifierButton *from, StatusNotifierButton *to); void sendTitle(QString arg); void sendstatus(QString arg); void cleansignal(); void iconReady(); void layoutReady(); void paramReady(); protected: void contextMenuEvent(QContextMenuEvent * event); void mouseReleaseEvent(QMouseEvent *event); void wheelEvent(QWheelEvent *event); void dragEnterEvent(QDragEnterEvent *e); void dragLeaveEvent(QDragLeaveEvent *e); void dragMoveEvent(QDragMoveEvent * e); void mouseMoveEvent(QMouseEvent *e); void mousePressEvent(QMouseEvent *e); bool event(QEvent *e); virtual QMimeData * mimeData(); void resizeEvent(QResizeEvent *event); void refetchIcon(Status status); void resetIcon(); private: void systemThemeChanges(); void updataItemMenu(); }; class StatusNotifierButtonMimeData: public QMimeData { Q_OBJECT public: StatusNotifierButtonMimeData(): QMimeData(), mButton(0) { } StatusNotifierButton *button() const { return mButton; } void setButton(StatusNotifierButton *button) { mButton = button; } private: StatusNotifierButton *mButton; }; #endif // STATUSNOTIFIERBUTTON_H ukui-panel-3.0.6.4/plugin-statusnotifier/statusnotifierwatcher.cpp0000644000175000017500000001321514203402514024075 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * LXQt - a lightweight, Qt based, desktop toolset * https://lxqt.org * * Copyright: 2015 LXQt team * Authors: * Balázs Béla * Paulo Lieuthier * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "statusnotifierwatcher.h" #include #include #include "dbusproperties.h" static const QString s_watcherServiceName(QStringLiteral("org.kde.StatusNotifierWatcher")); StatusNotifierWatcher::StatusNotifierWatcher(QObject *parent) : QObject(parent) { qRegisterMetaType("IconPixmap"); qDBusRegisterMetaType(); qRegisterMetaType("IconPixmapList"); qDBusRegisterMetaType(); qRegisterMetaType("ToolTip"); qDBusRegisterMetaType(); m_statusNotifierWatcher=NULL; init(); } StatusNotifierWatcher::~StatusNotifierWatcher() { QDBusConnection::sessionBus().unregisterService("org.kde.StatusNotifierWatcher"); } void StatusNotifierWatcher::init(){ if (QDBusConnection::sessionBus().isConnected()) { m_serviceName = "org.kde.StatusNotifierHost-" + QString::number(QCoreApplication::applicationPid()); QDBusConnection::sessionBus().registerService(m_serviceName); QDBusServiceWatcher *watcher = new QDBusServiceWatcher(s_watcherServiceName, QDBusConnection::sessionBus(), QDBusServiceWatcher::WatchForOwnerChange, this); connect(watcher, &QDBusServiceWatcher::serviceOwnerChanged, this, &StatusNotifierWatcher::serviceChange); registerWatcher(s_watcherServiceName); } } void StatusNotifierWatcher::registerWatcher(const QString& service) { //qCDebug(DATAENGINE_SNI)<<"service appeared"<isValid()) { m_statusNotifierWatcher->call(QDBus::NoBlock, QStringLiteral("RegisterStatusNotifierHost"), m_serviceName); OrgFreedesktopDBusPropertiesInterface propetriesIface(m_statusNotifierWatcher->service(), m_statusNotifierWatcher->path(), m_statusNotifierWatcher->connection()); QDBusPendingReply pendingItems = propetriesIface.Get(m_statusNotifierWatcher->interface(), "RegisteredStatusNotifierItems"); QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pendingItems, this); connect(watcher, &QDBusPendingCallWatcher::finished, this, [=]() { watcher->deleteLater(); QDBusReply reply = *watcher; QStringList registeredItems = reply.value().variant().toStringList(); foreach (const QString &service, registeredItems) { newItem(service); } }); connect(m_statusNotifierWatcher, &OrgKdeStatusNotifierWatcherInterface::StatusNotifierItemRegistered, this, &StatusNotifierWatcher::serviceRegistered); connect(m_statusNotifierWatcher, &OrgKdeStatusNotifierWatcherInterface::StatusNotifierItemUnregistered, this, &StatusNotifierWatcher::serviceUnregistered); } else { delete m_statusNotifierWatcher; m_statusNotifierWatcher = nullptr; } } } void StatusNotifierWatcher::serviceChange(const QString& name, const QString& oldOwner, const QString& newOwner) { qDebug()<< "Service" << name << "status change, old owner:" << oldOwner << "new:" << newOwner; if (newOwner.isEmpty()) { //unregistered unregisterWatcher(name); } else if (oldOwner.isEmpty()) { //registered registerWatcher(name); } } void StatusNotifierWatcher::unregisterWatcher(const QString& service) { if (service == s_watcherServiceName) { qDebug()<< s_watcherServiceName << "disappeared"; disconnect(m_statusNotifierWatcher, &OrgKdeStatusNotifierWatcherInterface::StatusNotifierItemRegistered, this, &StatusNotifierWatcher::serviceRegistered); disconnect(m_statusNotifierWatcher, &OrgKdeStatusNotifierWatcherInterface::StatusNotifierItemUnregistered, this, &StatusNotifierWatcher::serviceUnregistered); delete m_statusNotifierWatcher; m_statusNotifierWatcher = nullptr; } } void StatusNotifierWatcher::serviceRegistered(const QString &service) { qDebug() << "Registering"< Thu, 24 Dec 2020 15:10:02 +0800 + +ukui-panel (3.0.1-40~1224) v101; urgency=medium + + * 解决u盘图标不消失的问题 + + -- hepuyao Fri, 11 Dec 2020 13:49:52 +0800 + +ukui-panel (3.0.1-39) v101; urgency=medium + + * 任务栏判断配置文件异常 + 解决翻译文件“睡眠”和“休眠”统一 #27572 + 任务栏托盘图标高亮逻辑优化 #22328 + 修改判断右键是否需要添加系统监视器的接口 + + -- hepuyao Thu, 10 Dec 2020 20:25:05 +0800 ukui-panel-3.0.6.4/doc/ukui-panel-Requirements-Document.doc0000644000175000017500000003413514203402514022120 0ustar fengfengPK N@ docProps/PKN@^rdocProps/app.xmlQo0ߗ?ޡiLhrf6m5WdQ{MO܃Π ba{ ,>S36R¿ oT-a~m#dX -5[ )nuRWH%gԂ( Q@{'dʯCj|t8MXHbtwV`HQ?ԅ!FjʬSg~½tf?$M+MU}3 &-$m sFm*ww9J3j]yVqh7(yy͂d2˂(-U&Af8FQ0aIs{1nPKN@/>_docProps/core.xml[K0C}U]9(ޅVl$iu ^&'o|/*QZjS"ykyu{SpCjkpQ0)G){C1v| $*km%ah7063B w،F4(fg^ 8$(pzO.HY g^?#wmy_#O?j\8ߎr ̃;%jL~EfnB *w£Kj fw`ƹA2ݺx8cXOfqN~YNE*՗~PKN@h+docProps/custom.xmlMo EM{؎Tt&ΐ@[3wr_Nνl0K5%L4 e%|=:#YEznoسtAI"^B =H$&&u tgl^qZ>iia>`5q+_|2F݊}D ?ڬiیd$QBk'L!0_"VL<ԓIC1o>4MvS2*WrPK N@word/PKN@ > 2hword/styles.xml][sH~ߪOlcO\Q:5v[g[вzʯ݀Où|>& W4oyIx@4\|2ɣ%OYNx_.JY$e[:dbDiXiX켂8HEd.>\."՟ =JFeʳ0NOKkA^\&WJF}S꿍Ipx`H'H @eVLS()-_T4dYr'8ڇhrkh q<p 8q6:!%bړp#w9pwʎܝ#wI?pw)LP (C%( KP,4,AQhXаa 6/pȊoG )L<(+<t|t+Ph4{ꌘisw BTjb O8J ߏ M( F0!dIDƃLbtra-X"oy7[D$o, F\.mh4-X"<4DmF7rxcY\o,+:}ˆ7[D%o,xcI'Xxc\hj[D.yhmq뇸7zvtNUpD V_=~y@>O龍߼0x @*Fm/¸Ճk˵^d\;lNw-o\'ˮ́jEXR0x}ugO3]>4LCf6 Woh 1N\8'd 퐹tDq[W-%6[t'6K;e6_z5|yɓ䞙* ~0+F$|!ۣC#[C2?_1=\Tgn/3xĿ3x7Ňv<."P`7x0қ.Bih[(+W\=6 s`ήC:Y{Ib~ 5?p۬j82PKN@^# word/settings.xmlV[s8~ߙ t :}F$_# f:s|H ہ6LI \Ln'鿋zRYP$L=]7kQЄ4'Qim &/APs*(-Oꪟ+QQ2ƙFeԙQ2L˵2jcJ6C4sm=4pAISkWae0{+AoIv6J/?Sl>]A|1 K=t#]\LSیpQ+ZZw@6v)A=,:xkdh $7IS>, ƣִԬe9iEs$V0SqS=cf }|0#鑷Tߢ xP#HkۺNOWyqQqkN99 \Bwl בhd85mYMY[Oh*1i6+X\,-]1 w]J8 ݫڶ~~'a Dv{f Ukv)x0_ ms,){,>a 7GV ]i}W@bqWgmg՚,p:~٠I|B*L8|a mv?_ '8#rEȌ̎9WWd/:xd1Op={Ekys>%b|~sEc2:e'wikr [*2hoIfL~5'=9:sشfn'ORq}zv4菸w+ѴP$αtSgiВx5bP&hGjE[d1uj0:g`:uXӪ7ƓU;5_>Hڏl;x_~% #Ju<4n@2A$%L> GG(U] N#/B;Kpf)S1W#;PK N@ word/theme/PKN@Ѯ$word/theme/theme1.xmlYMo7X콱d#2">vDJ)-ˈ\݊X@Ѵȡ^z(HhkHS CjEJT>E}3|!WWޏw ,iK%ɐ$ ~˾'$JDY և\A21>GRkkbH\b)NوIõ#ӵR#^bp{c4"C?f;HPC{7L46BLErѦ쨏KߣHHxK_ۺ6s#*Wv]x]A1iRԶ @2S:ŸVq1}Vw;j5@GvQ%Uo5(_Yw-נ _]W*VkP-vn5($/KFk2bt oT+z|j(KM1b\Uk1x H$')!q Q2'a$4h#y64KCjFO 9Ie$E1^߾g~=~/#j%i/y<ڍ&ϟ?Wn l9Wnb3nb; J## }}(rv;D6gE|"^[(쩹0'I螜OL-]sPb3IA=e+͛%8Scb 9l$A>X47%1e"bspaԵ6>+ucjH\QL̀#H|h:BBCL .k$}ĝ:m$d3m6nE(N]I"C"&.wy@t!JjpӤ4/dU)!R$'w6 7Ho8x_TĹgvznQ[sM6rz/ߋ|EM1^a;f w. 10ʫ KQ& 1^ Gs4b(K|5拾?T$&s/B")2q]W"L*kD<4$p|{JVcp>ST5 gQVc /A[C`u-( VI*mP  qLR"Nڼ#!>VEvɓ -}%-.(h6xŸۥ^b4!RJ=k*(UXQ]bC Ƿ4kz ykE} #ؑR}ߗ6T@G@ΨrRWYiī %z*^M  uG.'N:՛J)E rH|lJ19;,*;(»]T;ccxTߩx'HEFY1pxiǻ*QZt I2<_jKh';{;XخYiؽKmr+2mbvQ8*NۑTD;7V@q9mrż3a=BϪDA5@ҎJvI#H5c5͉/脰ҵGw&/WSUiHe8}L]$V Γ'1$"v](qV20WhA@v{El)[ME8Yadڥ(e(,MFuӪ0oiA҄Mm(\_19oCqHǼE񯬭t{` H"ϭc {hf]s?'^{P TW 'uC"jxD(( 3x .ҡ&C. dpp<]r.#lA錑//7nnSfg׵ܑ=B1CFM{ϕ}D+x6e@AG׽JAzZPt!n4;_x2i{{N9H3V&kŕBo~/`~놱02pG+K|Š S?\o=ߗ=dpQĎ7Ah429#dL1j*c\$[ֳ I٤˘ IYt# Hˍ[+;$q{M1#3ڦ0WZX'ell-] k˘\ILamy!XFI\!> +p@ӳhْل!sx;_52X\%mOVf6fVΜ 0x_Ic 1yֵB3?y*m#-d.OU8>2X4fF~g}_[o楣U6A2>`jpUaAX{a-…n'sDQyWGy+HO+f-:}T~I<< NeԾucd'}x 620Z䷦\#7jɸ-0-}XO6޽n-&^@q+s߹cdޘ&(xBC]wġ 3ߐ&'LzPPk禱f }@s,3]6&r7֣lHUk mXH^E (XG!f+uc6gbPŎjNݵ2wyIͯ~SxAT|.C'2<X)G=_+D1fruM3}952Ak,Z(/ _"eC^M0b^{)ֻLX*󑟈<(ť|*qQn4 χJDj7H_OH'h.˫|B17N ZuN+`m%8/ben )ۮBrγ?qƍBSn'8~,+llWkgz8JW9鏅­$y%>Po[6 v:/꺵 n;6;eA0;muĜ@Znwf~<89_fC͎zRqOI Oi>jrN%.nw#Tԣ F)S r^EupM(SbMK C9}x|A1 uRWQTAgig>A40%viXdTxV`Ssr[%b'2+,G8Y$el]'0Ԁo!O4gM4Y7J(rP_mQh^(~D T|$C}F^9 ex?r7/y$ȪEHin*gREmgXeNt{"_$'ܻeEga(6d2'OvpR/0q7gaoWπNcފ wY"!E Ntާ3lWB߷.%lb'N}PK N@ customXml/PKN@>ϕcustomXml/item1.xml 0DnՋ$=xivSѿPśיyÓţݍzR%)G-]\·C<9OPJrn'L0b>!Vp acI8iZ*oQmp7 IkX 3OuPKN@cC{EGcustomXml/itemProps1.xmleQk0r5Fb,N`!^ۀI17t}{9]\ph4!@-L'kXuZՏUgw:3ѡ Byl|imބIM\а!LfC,k =28;7n ⌊ȌٛIqt"ƈYv$'"f{{+j$ReFBSiJu7? uEW}{ PKN@^}word/numbering.xmln0  ]֭F[!P X,Bu$ۏAIƲEO̓QKeJ(SQIT@o(s%iԢ].#`HwvNIbIM`(*%UUФSL.,ߴQZ Xآ'4\2;+O6^]cv3wvz9aT#Q"! h\3≼CZFP4(ike%֓"Z'NgYPKf6Q3( >3N#H89)ɀy[kN G=Oh>F?P^'4*($2xAQ-#Gxg5":ڔJ{iY }J_QEM[ʷM'gponNh>ON-d3.C(i"gddEk,(eM2]o/zEC*ch4/ s4w0S78][fy>(QD9+Խ}qw+JBLh6uex֘"q6+)*O~QogTIy?t4KZ Y(z2BFl.v/7eXg|NDQq&ت<< FsסM8Z.܋ 8g7)kBpQT T0s܏·dle=$7QRfkCȃ5XSF#AD*¡zU:d*SR4 ?5_~?u'oeh| mKVmb+ˇP]P"{ xǡ(+*lh!tssP T5I؝N3`yngClWvBd)I dP;"LNTδZ@"(TSi\ETC=P] C1NʆS'IcxAiYhhê/Ke,(I$ 4(V tgT¶`.MۆW^`c(iQ/^Qļ(QzZb fI:IR@^lo5c(BRrT\i*͞͡'ȥTʝUG=( S'@VT`ܳ3h;l_92qHvJ0Cq<$IMF4&X58Ũ*c}ƾ|M\5IuDb1 #s~ôs>VYHWsEuiX4[ݵܮ5փ/JfﵚfK`̧:nzM7=ptQBc0vʍL٨j+㝔Y0W!/6$\ɈzU]ikANl;tr(Θ:b!i> rfu>JG1ے7Pay,]1<h|Tn,PYkZA@ k9rq6ԵPlVT~ɲB9]:ڍj#1e~1s:8i{!leAAֽ !=޹7Gl7fɛ} PKN@x E1[Content_Types].xmlPK N@e-_rels/PKN@""  -_rels/.relsPK N@ $customXml/PK N@.customXml/_rels/PKN@t?9z( .customXml/_rels/item1.xml.relsPKN@>ϕ $customXml/item1.xmlPKN@cC{EG %customXml/itemProps1.xmlPK N@ docProps/PKN@^r 'docProps/app.xmlPKN@/>_ docProps/core.xmlPKN@h+ docProps/custom.xmlPK N@Oword/PK N@ /word/_rels/PKN@&J  /word/_rels/document.xml.relsPKN@-CrlT s Aword/document.xmlPKN@* H" )word/fontTable.xmlPKN@^} &word/numbering.xmlPKN@^#  word/settings.xmlPKN@ > 2h rword/styles.xmlPK N@ word/theme/PKN@Ѯ$ word/theme/theme1.xmlPKY2ukui-panel-3.0.6.4/NEWS0000644000175000017500000000013214203402514013042 0ustar fengfeng### ukui-panel 2.0.0 * fork from lxqt-panel ### ukui-panel 1.0.0 * Initial release. ukui-panel-3.0.6.4/COPYING0000644000175000017500000005763614203402514013423 0ustar fengfeng GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS ukui-panel-3.0.6.4/CMakeLists.txt.user0000644000175000017500000010020314204636772016100 0ustar fengfeng EnvironmentId {3038e3fa-6365-4b5d-966e-fb8a038fe43e} ProjectExplorer.Project.ActiveTarget 0 ProjectExplorer.Project.EditorSettings true false true Cpp CppGlobal QmlJS QmlJSGlobal 2 UTF-8 false 4 false 80 true true 1 true false 0 true true 0 8 true 1 true true true false ProjectExplorer.Project.PluginSettings ProjectExplorer.Project.Target.0 桌面 桌面 {14f66096-8afd-4aba-8f2a-8af0c9639e1f} 0 0 2 CMAKE_BUILD_TYPE:STRING=Debug CMAKE_CXX_COMPILER:STRING=%{Compiler:Executable:Cxx} CMAKE_C_COMPILER:STRING=%{Compiler:Executable:C} CMAKE_PREFIX_PATH:STRING=%{Qt:QT_INSTALL_PREFIX} QT_QMAKE_EXECUTABLE:STRING=%{Qt:qmakeExecutable} /home/kylin/bxq/bxq-ukui-panel/build-ukui-panel-unknown-Debug all true CMakeProjectManager.MakeStep 1 Build Build ProjectExplorer.BuildSteps.Build clean true CMakeProjectManager.MakeStep 1 Clean Clean ProjectExplorer.BuildSteps.Clean 2 false Debug CMakeProjectManager.CMakeBuildConfiguration CMAKE_BUILD_TYPE:STRING=Release CMAKE_CXX_COMPILER:STRING=%{Compiler:Executable:Cxx} CMAKE_C_COMPILER:STRING=%{Compiler:Executable:C} CMAKE_PREFIX_PATH:STRING=%{Qt:QT_INSTALL_PREFIX} QT_QMAKE_EXECUTABLE:STRING=%{Qt:qmakeExecutable} /home/kylin/bxq/bxq-ukui-panel/build-ukui-panel-unknown-Release all true CMakeProjectManager.MakeStep 1 Build Build ProjectExplorer.BuildSteps.Build clean true CMakeProjectManager.MakeStep 1 Clean Clean ProjectExplorer.BuildSteps.Clean 2 false Release CMakeProjectManager.CMakeBuildConfiguration CMAKE_BUILD_TYPE:STRING=RelWithDebInfo CMAKE_CXX_COMPILER:STRING=%{Compiler:Executable:Cxx} CMAKE_C_COMPILER:STRING=%{Compiler:Executable:C} CMAKE_PREFIX_PATH:STRING=%{Qt:QT_INSTALL_PREFIX} QT_QMAKE_EXECUTABLE:STRING=%{Qt:qmakeExecutable} /home/kylin/bxq/bxq-ukui-panel/build-ukui-panel-unknown-RelWithDebInfo all true CMakeProjectManager.MakeStep 1 Build Build ProjectExplorer.BuildSteps.Build clean true CMakeProjectManager.MakeStep 1 Clean Clean ProjectExplorer.BuildSteps.Clean 2 false Release with Debug Information CMakeProjectManager.CMakeBuildConfiguration CMAKE_BUILD_TYPE:STRING=MinSizeRel CMAKE_CXX_COMPILER:STRING=%{Compiler:Executable:Cxx} CMAKE_C_COMPILER:STRING=%{Compiler:Executable:C} CMAKE_PREFIX_PATH:STRING=%{Qt:QT_INSTALL_PREFIX} QT_QMAKE_EXECUTABLE:STRING=%{Qt:qmakeExecutable} /home/kylin/bxq/bxq-ukui-panel/build-ukui-panel-unknown-MinSizeRel all true CMakeProjectManager.MakeStep 1 Build Build ProjectExplorer.BuildSteps.Build clean true CMakeProjectManager.MakeStep 1 Clean Clean ProjectExplorer.BuildSteps.Clean 2 false Minimum Size Release CMakeProjectManager.CMakeBuildConfiguration 4 0 Deploy Deploy ProjectExplorer.BuildSteps.Deploy 1 ProjectExplorer.DefaultDeployConfiguration 1 dwarf cpu-cycles 250 -e cpu-cycles --call-graph dwarf,4096 -F 250 -F true 4096 false false 1000 true false false false false true 0.01 10 true kcachegrind 1 25 1 true false true valgrind 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 2 test-repair-dialog CMakeProjectManager.CMakeRunConfiguration.test-repair-dialog test-repair-dialog false false true true false false true dwarf cpu-cycles 250 -e cpu-cycles --call-graph dwarf,4096 -F 250 -F true 4096 false false 1000 true false false false false true 0.01 10 true kcachegrind 1 25 1 true false true valgrind 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 2 ukui-flash-disk CMakeProjectManager.CMakeRunConfiguration.ukui-flash-disk ukui-flash-disk false false true true false false true dwarf cpu-cycles 250 -e cpu-cycles --call-graph dwarf,4096 -F 250 -F true 4096 false false 1000 true false false false false true 0.01 10 true kcachegrind 1 25 1 true false true valgrind 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 2 ukui-panel CMakeProjectManager.CMakeRunConfiguration.ukui-panel ukui-panel false false true true false false true 3 ProjectExplorer.Project.TargetCount 1 ProjectExplorer.Project.Updater.FileVersion 22 Version 22 ukui-panel-3.0.6.4/.github/0000755000175000017500000000000014203402514013707 5ustar fengfengukui-panel-3.0.6.4/.github/workflows/0000755000175000017500000000000014203402514015744 5ustar fengfengukui-panel-3.0.6.4/.github/workflows/build.yml0000644000175000017500000000741514203402514017575 0ustar fengfengname: Check build on: push: branches: - master pull_request: branches: - master schedule: - cron: '0 0 * * *' jobs: archlinux: name: on Archlinux runs-on: ubuntu-20.04 container: docker.io/library/archlinux:latest steps: - name: Checkout ukui-panel source code uses: actions/checkout@v2 - name: Refresh pacman repository and force upgrade run: pacman -Syyu --noconfirm - name: Install build dependencies run: pacman -S --noconfirm base-devel glibc qt5-base cmake qt5-tools dconf libdbusmenu-qt5 gsettings-qt kwindowsystem libqtxdg qt5-webkit peony - name: CMake configure & Make run: | mkdir build; cd build; cmake ..; make -j$(nproc); debian: name: on Debian Sid runs-on: ubuntu-20.04 container: docker.io/library/debian:sid env: DEBIAN_FRONTEND: noninteractive steps: - name: Checkout ukui-panel source code uses: actions/checkout@v2 - name: Update apt repository run: apt-get update -y - name: Install build dependcies run: apt-get install -y build-essential qt5-default qttools5-dev-tools debhelper-compat cmake libasound2-dev libdbusmenu-qt5-dev libglib2.0-dev libicu-dev libkf5solid-dev libkf5windowsystem-dev libpulse-dev libqt5svg5-dev libqt5x11extras5-dev libsensors4-dev libstatgrab-dev libsysstat-qt5-0-dev libx11-dev libxcb-damage0-dev libxcb-util0-dev libxcb-xkb-dev libxcomposite-dev libxdamage-dev libxkbcommon-dev libxkbcommon-x11-dev libxrender-dev libqt5webkit5-dev qttools5-dev libqt5xdg-dev libgsettings-qt-dev libpoppler-dev libpoppler-qt5-dev libpeony-dev libdconf-dev - name: CMake configure & Make run: | mkdir build; cd build; cmake ..; make -j$(nproc); fedora: name: on Fedora 32 runs-on: ubuntu-20.04 container: docker.io/library/fedora:32 steps: - name: Checkout ukui-panel source code uses: actions/checkout@v2 - name: Install build dependencies run: dnf install -y make gcc gcc-c++ which cmake cmake-rpm-macros autoconf automake intltool rpm-build qt5-devel qt5-rpm-macros qt5-qtbase-devel qt5-qttools-devel glib2-devel qt5-qtbase-devel dbusmenu-qt5-devel gsettings-qt-devel kf5-kwindowsystem-devel poppler-qt5-devel qt5-qtx11extras-devel qt5-qtbase-private-devel libqtxdg-devel libXcomposite-devel libXdamage-devel libXrender-devel dconf-devel libxcb-devel xcb-util-devel xcb-util-cursor-devel xcb-util-keysyms-devel xcb-util-image-devel xcb-util-wm-devel xcb-util-renderutil-devel - name: CMake configure & Make run: | mkdir build; cd build; cmake ..; make -j$(nproc); ubuntu: name: on Ubuntu 20.04 runs-on: ubuntu-20.04 container: docker.io/library/ubuntu:focal env: DEBIAN_FRONTEND: noninteractive steps: - name: Checkout ukui-panel source code uses: actions/checkout@v2 - name: Update apt repository run: apt-get update -y - name: Install build dependcies run: apt-get install -y build-essential qt5-default qttools5-dev-tools debhelper-compat cmake libasound2-dev libdbusmenu-qt5-dev libglib2.0-dev libicu-dev libkf5solid-dev libkf5windowsystem-dev libpulse-dev libqt5svg5-dev libqt5x11extras5-dev libsensors4-dev libstatgrab-dev libsysstat-qt5-0-dev libx11-dev libxcb-damage0-dev libxcb-util0-dev libxcb-xkb-dev libxcomposite-dev libxdamage-dev libxkbcommon-dev libxkbcommon-x11-dev libxrender-dev libqt5webkit5-dev qttools5-dev libqt5xdg-dev libgsettings-qt-dev libpoppler-dev libpoppler-qt5-dev libpeony-dev libdconf-dev - name: CMake configure & Make run: | mkdir build; cd build; cmake ..; make -j$(nproc); ukui-panel-3.0.6.4/plugin-startbar/0000755000175000017500000000000014203402514015465 5ustar fengfengukui-panel-3.0.6.4/plugin-startbar/startmenu_button.cpp0000644000175000017500000001772214203402514021617 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see setIcon(QIcon::fromTheme("kylin-startmenu",QIcon("/usr/share/ukui-panel/panel/img/startmenu.svg"))); this->setStyle(new CustomStyle()); QTimer::singleShot(5000,[this] {this->setToolTip(tr("UKUI Menu")); }); this->setIconSize(QSize(m_plugin->panel()->iconSize(),m_plugin->panel()->iconSize())); } StartMenuButton::~StartMenuButton() { } /*plugin-startmenu refresh function*/ void StartMenuButton::realign() { if (m_plugin->panel()->isHorizontal()) this->setFixedSize(m_plugin->panel()->panelSize()*1.3,m_plugin->panel()->panelSize()); else this->setFixedSize(m_plugin->panel()->panelSize(),m_plugin->panel()->panelSize()*1.3); this->setIconSize(QSize(m_plugin->panel()->iconSize(),m_plugin->panel()->iconSize())); } void StartMenuButton::mousePressEvent(QMouseEvent* event) { const Qt::MouseButton b = event->button(); if (Qt::LeftButton == b) { if(QFileInfo::exists(QString("/usr/bin/ukui-menu"))) { QProcess *process =new QProcess(this); process->startDetached("/usr/bin/ukui-menu"); process->deleteLater(); } else{qDebug()<<"not find /usr/bin/ukui-start-menu"<setAttribute(Qt::WA_DeleteOnClose); QMenu *pUserAction=new QMenu(tr("User Action")); //用户操作 QMenu *pSleepHibernate=new QMenu(tr("Sleep or Hibernate")); //重启或休眠 QMenu *pPowerSupply=new QMenu(tr("Power Supply")); //电源 rightPressMenu->addMenu(pUserAction); rightPressMenu->addMenu(pSleepHibernate); rightPressMenu->addMenu(pPowerSupply); pUserAction->addAction(QIcon::fromTheme("system-lock-screen-symbolic"), tr("Lock Screen"), this, SLOT(ScreenServer()) ); //锁屏 if (hasMultipleUsers()) { pUserAction->addAction(QIcon::fromTheme("stock-people-symbolic"), tr("Switch User"), this, SLOT(SessionSwitch()) ); //切换用户 } pUserAction->addAction(QIcon::fromTheme("ukui-system-logout-symbolic"), tr("Logout"), this, SLOT(SessionLogout()) ); //注销 if(QString::compare(getCanHibernateResult(),"yes") == 0){ pSleepHibernate->addAction(QIcon::fromTheme("kylin-sleep-symbolic"), tr("Hibernate Mode"), this, SLOT(SessionHibernate()) ); //休眠 } pSleepHibernate->addAction(QIcon::fromTheme("ukui-hebernate-symbolic"), tr("Sleep Mode"), this, SLOT(SessionSuspend()) ); //睡眠 pPowerSupply->addAction(QIcon::fromTheme("ukui-system-restart-symbolic"), tr("Restart"), this, SLOT(SessionReboot()) ); //重启 QFileInfo file("/usr/bin/time-shutdown"); if(file.exists()) pPowerSupply->addAction(QIcon::fromTheme("ukui-shutdown-timer-symbolic"), tr("TimeShutdown"), this, SLOT(TimeShutdown()) ); //定时开关机 pPowerSupply->addAction(QIcon::fromTheme("system-shutdown-symbolic"), tr("Power Off"), this, SLOT(SessionShutdown()) ); //关机 rightPressMenu->setGeometry(m_plugin->panel()->calculatePopupWindowPos(mapToGlobal(event->pos()), rightPressMenu->sizeHint())); rightPressMenu->show(); } /*开始菜单按钮右键菜单选项,与开始菜单中电源按钮的右键功能是相同的*/ //锁屏 void StartMenuButton::ScreenServer() { system("ukui-screensaver-command -l"); } //切换用户 void StartMenuButton::SessionSwitch() { QProcess::startDetached(QString("ukui-session-tools --switchuser")); } //注销 void StartMenuButton::SessionLogout() { system("ukui-session-tools --logout"); } //休眠 睡眠 void StartMenuButton::SessionHibernate() { system("ukui-session-tools --hibernate"); } //睡眠 void StartMenuButton::SessionSuspend() { system("ukui-session-tools --suspend"); } //重启 void StartMenuButton::SessionReboot() { system("ukui-session-tools --reboot"); } //定时关机 void StartMenuButton::TimeShutdown() { QProcess *process_timeshutdowm =new QProcess(this); process_timeshutdowm->startDetached("/usr/bin/time-shutdown"); process_timeshutdowm->deleteLater(); } //关机 void StartMenuButton::SessionShutdown() { system("ukui-session-tools --shutdown"); } //获取系统版本,若为ubuntu则取消休眠功能 void StartMenuButton::getOsRelease() { QFile file("/etc/lsb-release"); if (!file.open(QIODevice::ReadOnly)) qDebug() << "Read file Failed."; while (!file.atEnd()) { QByteArray line = file.readLine(); QString str(line); if (str.contains("DISTRIB_ID")){ version=str.remove("DISTRIB_ID="); version=str.remove("\n"); } } } //检测当前系统能否执行休眠操作 QString StartMenuButton::getCanHibernateResult() { QDBusInterface interface("org.freedesktop.login1", "/org/freedesktop/login1", "org.freedesktop.login1.Manager", QDBusConnection::systemBus()); if (!interface.isValid()) { qCritical() << QDBusConnection::sessionBus().lastError().message(); } /*调用远程的 CanHibernate 方法,判断是否可以执行休眠的操作,返回值为yes为允许执行休眠,no为无法执行休眠 na为交换分区不足*/ QDBusReply reply = interface.call("CanHibernate"); if (reply.isValid()) { return reply; } else { qCritical() << "Call Dbus method failed"; } } bool StartMenuButton::hasMultipleUsers() { QDBusInterface interface("org.freedesktop.Accounts", "/org/freedesktop/Accounts", "org.freedesktop.DBus.Properties", QDBusConnection::systemBus()); if (!interface.isValid()) { qCritical() << QDBusConnection::systemBus().lastError().message(); return false; } QDBusReply reply = interface.call("Get","org.freedesktop.Accounts","HasMultipleUsers"); return reply.value().toBool(); } void StartMenuButton::enterEvent(QEvent *) { repaint(); return; } void StartMenuButton::leaveEvent(QEvent *) { repaint(); return; } ukui-panel-3.0.6.4/plugin-startbar/startmenu_button.h0000644000175000017500000000352614203402514021261 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include #include #include #include #include #include #include "../panel/iukuipanelplugin.h" #include "../panel/customstyle.h" class StartMenuButton : public QToolButton { Q_OBJECT public: StartMenuButton(IUKUIPanelPlugin *plugin,QWidget* parent = 0); ~StartMenuButton(); void realign(); protected: void contextMenuEvent(QContextMenuEvent *event); void mousePressEvent(QMouseEvent* event); void enterEvent(QEvent *); void leaveEvent(QEvent *); private: QMenu *rightPressMenu; IUKUIPanelPlugin * m_plugin; QString version; QWidget *m_parent; void getOsRelease(); QString getCanHibernateResult(); bool hasMultipleUsers(); private slots: void ScreenServer(); void SessionSwitch(); void SessionLogout(); void SessionReboot(); void TimeShutdown(); void SessionShutdown(); void SessionSuspend(); void SessionHibernate(); }; #endif // STARTMENUBUTTON_H ukui-panel-3.0.6.4/plugin-startbar/taskview_button.cpp0000644000175000017500000000562014203402514021424 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see setParent(parent); setFocusPolicy(Qt::NoFocus); setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); this->setToolTip(tr("Show Taskview")); this->setStyle(new CustomStyle()); this->setIcon(QIcon::fromTheme("taskview",QIcon("/usr/share/ukui-panel/panel/img/taskview.svg"))); this->setIconSize(QSize(m_plugin->panel()->iconSize(),m_plugin->panel()->iconSize())); } TaskViewButton::~TaskViewButton(){ } void TaskViewButton::realign() { if (m_plugin->panel()->isHorizontal()) { this->setFixedSize(m_plugin->panel()->panelSize(),m_plugin->panel()->panelSize()); } else { this->setFixedSize(m_plugin->panel()->panelSize(),m_plugin->panel()->panelSize()); } this->setIconSize(QSize(m_plugin->panel()->iconSize(),m_plugin->panel()->iconSize())); } void TaskViewButton::mousePressEvent(QMouseEvent *event) { const Qt::MouseButton b = event->button(); #if 0 //调用dbus接口 QString object = QString(getenv("DISPLAY")); object = object.trimmed().replace(":", "_").replace(".", "_").replace("-", "_"); object = "/org/ukui/WindowSwitch/display/" + object; QDBusInterface interface("org.ukui.WindowSwitch", object, "org.ukui.WindowSwitch", QDBusConnection::sessionBus()); if (!interface.isValid()) { qCritical() << QDBusConnection::sessionBus().lastError().message(); } if (Qt::LeftButton == b && interface.isValid()) { /* Call binary display task view * system("ukui-window-switch --show-workspace"); */ /*调用远程的value方法*/ QDBusReply reply = interface.call("handleWorkspace"); if (reply.isValid()) { if (!reply.value()) qWarning() << "Handle Workspace View Failed"; } else { qCritical() << "Call Dbus method failed"; } } #endif //调用命令 if (Qt::LeftButton == b){ system("ukui-window-switch --show-workspace"); } QWidget::mousePressEvent(event); } ukui-panel-3.0.6.4/plugin-startbar/startbar.cpp0000644000175000017500000000745314203402514020024 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include #include #include "../panel/customstyle.h" #define THEME_QT_SCHEMA "org.ukui.style" #define THEME_Style_Name "styleName" #define UKUI_PANEL_SETTINGS "org.ukui.panel.settings" #define SHOW_TASKVIEW "showtaskview" UKUIStartbarPlugin::UKUIStartbarPlugin(const IUKUIPanelPluginStartupInfo &startupInfo): QObject(), IUKUIPanelPlugin(startupInfo), m_widget(new UKUIStartBarWidget(this)) { m_widget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); } UKUIStartbarPlugin::~UKUIStartbarPlugin() { delete m_widget; } QWidget *UKUIStartbarPlugin::widget() { return m_widget; } void UKUIStartbarPlugin::realign() { m_widget->realign(); } UKUIStartBarWidget::UKUIStartBarWidget( IUKUIPanelPlugin *plugin, QWidget* parent ): m_plugin(plugin) { translator(); m_startMenuButton=new StartMenuButton(plugin,this); m_layout=new UKUi::GridLayout(this); m_layout->addWidget(m_startMenuButton); const QByteArray id(UKUI_PANEL_SETTINGS); if(QGSettings::isSchemaInstalled(id)) { m_gsettings = new QGSettings(id); } connect(m_gsettings, &QGSettings::changed, this, [=] (const QString &key){ if(key==SHOW_TASKVIEW) realign(); }); realign(); } void UKUIStartBarWidget::translator(){ m_translator = new QTranslator(this); QString locale = QLocale::system().name(); if (locale == "zh_CN"){ if (m_translator->load(QM_INSTALL)) qApp->installTranslator(m_translator); else qDebug() <deleteLater(); m_taskViewButton->deleteLater(); } /*plugin-startmenu refresh function*/ void UKUIStartBarWidget::realign() { if(m_gsettings->get(SHOW_TASKVIEW).toBool()){ if (!this->findChild("TaskViewButton")) { m_taskViewButton=new TaskViewButton(m_plugin,this); m_taskViewButton->setObjectName("TaskViewButton"); m_layout->addWidget(m_taskViewButton); } } else { if (this->findChild("TaskViewButton")) { if (m_taskViewButton != nullptr) { m_layout->removeWidget(m_taskViewButton); m_taskViewButton->deleteLater(); } } else { m_startMenuButton->realign(); return; } } if (m_plugin->panel()->isHorizontal()){ m_layout->setColumnCount(m_layout->count()); m_layout->setRowCount(0); // this->setFixedSize(m_plugin->panel()->panelSize()*2.3,m_plugin->panel()->panelSize()); }else{ m_layout->setRowCount(m_layout->count()); m_layout->setColumnCount(0); // this->setFixedSize(m_plugin->panel()->panelSize(),m_plugin->panel()->panelSize()*2.3); } m_startMenuButton->realign(); m_taskViewButton->realign(); } ukui-panel-3.0.6.4/plugin-startbar/startbar.h0000644000175000017500000000505114203402514017461 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include #include #include #include #include #include #include #include "../panel/ukuipanel.h" #include #include #include "../panel/highlight-effect.h" #include #include "startmenu_button.h" #include "taskview_button.h" #include "../panel/common/ukuigridlayout.h" class UKUIStartBarWidget; class UKUIStartbarPlugin: public QObject, public IUKUIPanelPlugin { Q_OBJECT public: explicit UKUIStartbarPlugin(const IUKUIPanelPluginStartupInfo &startupInfo); ~UKUIStartbarPlugin(); virtual QWidget *widget(); virtual QString themeId() const { return "startbar"; } virtual Flags flags() const { return NeedsHandle; } void realign(); bool isSeparate() const { return true; } private: UKUIStartBarWidget *m_widget; }; class StartBarLibrary: public QObject, public IUKUIPanelPluginLibrary { Q_OBJECT Q_PLUGIN_METADATA(IID "ukui.org/Panel/PluginInterface/3.0") Q_INTERFACES(IUKUIPanelPluginLibrary) public: IUKUIPanelPlugin *m_plugin; IUKUIPanelPlugin *instance(const IUKUIPanelPluginStartupInfo &startupInfo) const { return new UKUIStartbarPlugin(startupInfo); } }; class UKUIStartBarWidget:public QFrame { Q_OBJECT public: UKUIStartBarWidget(IUKUIPanelPlugin *plugin, QWidget* parent = 0); ~UKUIStartBarWidget(); void realign(); protected: private: IUKUIPanelPlugin *m_plugin; StartMenuButton *m_startMenuButton; TaskViewButton *m_taskViewButton; UKUi::GridLayout *m_layout; QTranslator *m_translator; QGSettings *m_gsettings; private: void translator(); }; #endif ukui-panel-3.0.6.4/plugin-startbar/img/0000755000175000017500000000000014203402514016241 5ustar fengfengukui-panel-3.0.6.4/plugin-startbar/img/search.png0000644000175000017500000000144014203402514020213 0ustar fengfengPNG  IHDR szzIDATXV;KQπŠ Xܙ;.Z]PZ:Š]R”v_Q!>@MQ3/`9~yseG B2 !1.7x83.RZg@8~:c$NKRW/c-ď>םkԛJ̓*ILJN9C $C@{oCTg=yQfZ%E{8 rvï".B@qָh3Ff+sRR8yp7L#Nh8]6!_UX*韥&Z{<&\wj!^{s1nZQ⾔ ,mH\=8hk@q6phbn8zX7 w'ߴ\.׋D+(#q\{7(M,'IENDB`ukui-panel-3.0.6.4/plugin-startbar/resources/0000755000175000017500000000000014203402514017477 5ustar fengfengukui-panel-3.0.6.4/plugin-startbar/resources/startbar.desktop.in0000644000175000017500000000015214203402514023317 0ustar fengfeng[Desktop Entry] Type=Service ServiceTypes=UKUIPanel/Plugin Name=Startbar Comment=startbar Icon=start-menu ukui-panel-3.0.6.4/plugin-startbar/CMakeLists.txt0000644000175000017500000000060714203402514020230 0ustar fengfengset(PLUGIN "startbar") set(HEADERS startbar.h startmenu_button.h taskview_button.h ) set(SOURCES startbar.cpp startmenu_button.cpp taskview_button.cpp ) set(UIS ) set(LIBRARIES ) install(FILES img/search.png DESTINATION "${PACKAGE_DATA_DIR}/plugin-assistant/img" COMPONENT Runtime ) ukui_plugin_translate_ts(${PLUGIN}) BUILD_UKUI_PLUGIN(${PLUGIN}) ukui-panel-3.0.6.4/plugin-startbar/translation/0000755000175000017500000000000014203402514020023 5ustar fengfengukui-panel-3.0.6.4/plugin-startbar/translation/startbar_zh_CN.ts0000644000175000017500000000510514203402514023277 0ustar fengfeng StartMenuButton UKui Menu 开始菜单 UKUI Menu 开始菜单 User Action 用户操作 Sleep or Hibernate 休眠或睡眠 Power Supply 电源 Lock Screen 锁定屏幕 Switch User 切换用户 Logout 注销 Hibernate Mode 休眠 Sleep Mode 睡眠 Restart 重启 TimeShutdown 定时关机 Power Off 关机 TaskViewButton Show Taskview 显示任务视图 ukui-panel-3.0.6.4/plugin-startbar/taskview_button.h0000644000175000017500000000231514203402514021067 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include "../panel/customstyle.h" #include "../panel/iukuipanelplugin.h" class TaskViewButton :public QToolButton { Q_OBJECT public: TaskViewButton(IUKUIPanelPlugin *plugin,QWidget *parent=nullptr); ~TaskViewButton(); void realign(); protected: void mousePressEvent(QMouseEvent* event); private: QWidget *m_parent; IUKUIPanelPlugin * m_plugin; }; #endif // TASKVIEWBUTTON_H ukui-panel-3.0.6.4/ukui-calendar/0000755000175000017500000000000014203402514015073 5ustar fengfengukui-panel-3.0.6.4/ukui-calendar/xatom-helper.cpp0000644000175000017500000001374614203402514020217 0ustar fengfeng/* * KWin Style UKUI * * Copyright (C) 2020, KylinSoft Co., Ltd. * * 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 3 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. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Authors: Yue Lan * */ #include "xatom-helper.h" #include #include #include #include static XAtomHelper *global_instance = nullptr; XAtomHelper *XAtomHelper::getInstance() { if (!global_instance) global_instance = new XAtomHelper; return global_instance; } bool XAtomHelper::isFrameLessWindow(int winId) { auto hints = getInstance()->getWindowMotifHint(winId); if (hints.flags == MWM_HINTS_DECORATIONS && hints.functions == 1) { return true; } return false; } bool XAtomHelper::isWindowDecorateBorderOnly(int winId) { return isWindowMotifHintDecorateBorderOnly(getInstance()->getWindowMotifHint(winId)); } bool XAtomHelper::isWindowMotifHintDecorateBorderOnly(const MotifWmHints &hint) { bool isDeco = false; if (hint.flags & MWM_HINTS_DECORATIONS && hint.flags != MWM_HINTS_DECORATIONS) { if (hint.decorations == MWM_DECOR_BORDER) isDeco = true; } return isDeco; } bool XAtomHelper::isUKUICsdSupported() { // fixme: return false; } bool XAtomHelper::isUKUIDecorationWindow(int winId) { if (m_ukuiDecorationAtion == None) return false; Atom type; int format; ulong nitems; ulong bytes_after; uchar *data; bool isUKUIDecoration = false; XGetWindowProperty(QX11Info::display(), winId, m_ukuiDecorationAtion, 0, LONG_MAX, false, m_ukuiDecorationAtion, &type, &format, &nitems, &bytes_after, &data); if (type == m_ukuiDecorationAtion) { if (nitems == 1) { isUKUIDecoration = data[0]; } } return isUKUIDecoration; } UnityCorners XAtomHelper::getWindowBorderRadius(int winId) { UnityCorners corners; Atom type; int format; ulong nitems; ulong bytes_after; uchar *data; if (m_unityBorderRadiusAtom != None) { XGetWindowProperty(QX11Info::display(), winId, m_unityBorderRadiusAtom, 0, LONG_MAX, false, XA_CARDINAL, &type, &format, &nitems, &bytes_after, &data); if (type == XA_CARDINAL) { if (nitems == 4) { corners.topLeft = static_cast(data[0]); corners.topRight = static_cast(data[1*sizeof (ulong)]); corners.bottomLeft = static_cast(data[2*sizeof (ulong)]); corners.bottomRight = static_cast(data[3*sizeof (ulong)]); } XFree(data); } } return corners; } void XAtomHelper::setWindowBorderRadius(int winId, const UnityCorners &data) { if (m_unityBorderRadiusAtom == None) return; ulong corners[4] = {data.topLeft, data.topRight, data.bottomLeft, data.bottomRight}; XChangeProperty(QX11Info::display(), winId, m_unityBorderRadiusAtom, XA_CARDINAL, 32, XCB_PROP_MODE_REPLACE, (const unsigned char *) &corners, sizeof (corners)/sizeof (corners[0])); } void XAtomHelper::setWindowBorderRadius(int winId, int topLeft, int topRight, int bottomLeft, int bottomRight) { if (m_unityBorderRadiusAtom == None) return; ulong corners[4] = {(ulong)topLeft, (ulong)topRight, (ulong)bottomLeft, (ulong)bottomRight}; XChangeProperty(QX11Info::display(), winId, m_unityBorderRadiusAtom, XA_CARDINAL, 32, XCB_PROP_MODE_REPLACE, (const unsigned char *) &corners, sizeof (corners)/sizeof (corners[0])); } void XAtomHelper::setUKUIDecoraiontHint(int winId, bool set) { if (m_ukuiDecorationAtion == None) return; XChangeProperty(QX11Info::display(), winId, m_ukuiDecorationAtion, m_ukuiDecorationAtion, 32, XCB_PROP_MODE_REPLACE, (const unsigned char *) &set, 1); } void XAtomHelper::setWindowMotifHint(int winId, const MotifWmHints &hints) { if (m_unityBorderRadiusAtom == None) return; XChangeProperty(QX11Info::display(), winId, m_motifWMHintsAtom, m_motifWMHintsAtom, 32, XCB_PROP_MODE_REPLACE, (const unsigned char *)&hints, sizeof (MotifWmHints)/ sizeof (ulong)); } MotifWmHints XAtomHelper::getWindowMotifHint(int winId) { MotifWmHints hints; if (m_unityBorderRadiusAtom == None) return hints; uchar *data; Atom type; int format; ulong nitems; ulong bytes_after; XGetWindowProperty(QX11Info::display(), winId, m_motifWMHintsAtom, 0, sizeof (MotifWmHints)/sizeof (long), false, AnyPropertyType, &type, &format, &nitems, &bytes_after, &data); if (type == None) { return hints; } else { hints = *(MotifWmHints *)data; XFree(data); } return hints; } XAtomHelper::XAtomHelper(QObject *parent) : QObject(parent) { if (!QX11Info::isPlatformX11()) return; m_motifWMHintsAtom = XInternAtom(QX11Info::display(), "_MOTIF_WM_HINTS", true); m_unityBorderRadiusAtom = XInternAtom(QX11Info::display(), "_UNITY_GTK_BORDER_RADIUS", false); m_ukuiDecorationAtion = XInternAtom(QX11Info::display(), "_KWIN_UKUI_DECORAION", false); } Atom XAtomHelper::registerUKUICsdNetWmSupportAtom() { // fixme: return None; } void XAtomHelper::unregisterUKUICsdNetWmSupportAtom() { // fixme: } ukui-panel-3.0.6.4/ukui-calendar/xatom-helper.h0000644000175000017500000000624314203402514017656 0ustar fengfeng/* * KWin Style UKUI * * Copyright (C) 2020, KylinSoft Co., Ltd. * * 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 3 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. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Authors: Yue Lan * */ #ifndef XATOMHELPER_H #define XATOMHELPER_H #include #include struct UnityCorners { ulong topLeft = 0; ulong topRight = 0; ulong bottomLeft = 0; ulong bottomRight = 0; }; typedef struct { ulong flags = 0; ulong functions = 0; ulong decorations = 0; long input_mode = 0; ulong status = 0; } MotifWmHints, MwmHints; #define MWM_HINTS_FUNCTIONS (1L << 0) #define MWM_HINTS_DECORATIONS (1L << 1) #define MWM_HINTS_INPUT_MODE (1L << 2) #define MWM_HINTS_STATUS (1L << 3) #define MWM_FUNC_ALL (1L << 0) #define MWM_FUNC_RESIZE (1L << 1) #define MWM_FUNC_MOVE (1L << 2) #define MWM_FUNC_MINIMIZE (1L << 3) #define MWM_FUNC_MAXIMIZE (1L << 4) #define MWM_FUNC_CLOSE (1L << 5) #define MWM_DECOR_ALL (1L << 0) #define MWM_DECOR_BORDER (1L << 1) #define MWM_DECOR_RESIZEH (1L << 2) #define MWM_DECOR_TITLE (1L << 3) #define MWM_DECOR_MENU (1L << 4) #define MWM_DECOR_MINIMIZE (1L << 5) #define MWM_DECOR_MAXIMIZE (1L << 6) #define MWM_INPUT_MODELESS 0 #define MWM_INPUT_PRIMARY_APPLICATION_MODAL 1 #define MWM_INPUT_SYSTEM_MODAL 2 #define MWM_INPUT_FULL_APPLICATION_MODAL 3 #define MWM_INPUT_APPLICATION_MODAL MWM_INPUT_PRIMARY_APPLICATION_MODAL #define MWM_TEAROFF_WINDOW (1L<<0) namespace UKUI { class Decoration; } class XAtomHelper : public QObject { friend class UKUI::Decoration; Q_OBJECT public: static XAtomHelper *getInstance(); static bool isFrameLessWindow(int winId); bool isWindowDecorateBorderOnly(int winId); bool isWindowMotifHintDecorateBorderOnly(const MotifWmHints &hint); bool isUKUICsdSupported(); bool isUKUIDecorationWindow(int winId); UnityCorners getWindowBorderRadius(int winId); void setWindowBorderRadius(int winId, const UnityCorners &data); void setWindowBorderRadius(int winId, int topLeft, int topRight, int bottomLeft, int bottomRight); void setUKUIDecoraiontHint(int winId, bool set = true); void setWindowMotifHint(int winId, const MotifWmHints &hints); MotifWmHints getWindowMotifHint(int winId); private: explicit XAtomHelper(QObject *parent = nullptr); Atom registerUKUICsdNetWmSupportAtom(); void unregisterUKUICsdNetWmSupportAtom(); Atom m_motifWMHintsAtom = None; Atom m_unityBorderRadiusAtom = None; Atom m_ukuiDecorationAtion = None; }; #endif // XATOMHELPER_H ukui-panel-3.0.6.4/ukui-calendar/lunarcalendarwidget/0000755000175000017500000000000014204636772021132 5ustar fengfengukui-panel-3.0.6.4/ukui-calendar/lunarcalendarwidget/frmlunarcalendarwidget.h0000644000175000017500000000355714203402514026021 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include "calendardbus.h" namespace Ui { class frmLunarCalendarWidget; } class frmLunarCalendarWidget : public QWidget { Q_OBJECT public: explicit frmLunarCalendarWidget(QWidget *parent = 0); ~frmLunarCalendarWidget(); void set_window_position(); bool status; protected: void paintEvent(QPaintEvent *); void mousePressEvent(QMouseEvent *event); private: Ui::frmLunarCalendarWidget *ui; QGSettings *transparency_gsettings; QGSettings *calendar_gsettings; CalendarDBus *mCalendarDBus; bool eventFilter(QObject *, QEvent *); private Q_SLOTS: void initForm(); void cboxCalendarStyle_currentIndexChanged(int index); void cboxSelectType_currentIndexChanged(int index); void cboxWeekNameFormat_currentIndexChanged(bool FirstDayisSun); void ckShowLunar_stateChanged(bool arg1); void changeUpSize(); void changeDownSize(); Q_SIGNALS: void yijiChangeUp(); void yijiChangeDown(); }; #endif // FRMLUNARCALENDARWIDGET_H ukui-panel-3.0.6.4/ukui-calendar/lunarcalendarwidget/picturetowhite.cpp0000644000175000017500000000570214203402514024701 0ustar fengfeng/* * Copyright (C) 2020 Tianjin KYLIN Information Technology Co., Ltd. * * 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 3, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see get(STYLE_NAME).toString()) && m_pgsettings->get(STYLE_NAME).toString() == STYLE_NAME_KEY_LIGHT) tray_icon_color = TRAY_ICON_COLOR_LOGHT; else tray_icon_color = TRAY_ICON_COLOR_DRAK; } connect(m_pgsettings, &QGSettings::changed, this, [=] (const QString &key) { if (key==STYLE_NAME) { if (stylelist.contains(m_pgsettings->get(STYLE_NAME).toString()) && m_pgsettings->get(STYLE_NAME).toString() == STYLE_NAME_KEY_LIGHT) tray_icon_color = TRAY_ICON_COLOR_LOGHT; else tray_icon_color = TRAY_ICON_COLOR_DRAK; } }); } QPixmap PictureToWhite::drawSymbolicColoredPixmap(const QPixmap &source) { QColor gray(128,128,128); QColor standard (31,32,34); QImage img = source.toImage(); for (int x = 0; x < img.width(); x++) { for (int y = 0; y < img.height(); y++) { auto color = img.pixelColor(x, y); if (color.alpha() > 0) { if (qAbs(color.red()-gray.red()) < 20 && qAbs(color.green()-gray.green()) < 20 && qAbs(color.blue()-gray.blue()) < 20) { color.setRed(tray_icon_color); color.setGreen(tray_icon_color); color.setBlue(tray_icon_color); img.setPixelColor(x, y, color); } else if (qAbs(color.red()-standard.red()) < 20 && qAbs(color.green()-standard.green()) < 20 && qAbs(color.blue()-standard.blue()) < 20) { color.setRed(tray_icon_color); color.setGreen(tray_icon_color); color.setBlue(tray_icon_color); img.setPixelColor(x, y, color); } else img.setPixelColor(x, y, color); } } } return QPixmap::fromImage(img); } ukui-panel-3.0.6.4/ukui-calendar/lunarcalendarwidget/frmlunarcalendarwidget.ui0000644000175000017500000001113014203402514026171 0ustar fengfeng frmLunarCalendarWidget 0 0 600 500 Form 0 0 0 0 0 0 整体样式 90 0 红色风格 选中样式 90 0 矩形背景 圆形背景 角标背景 图片背景 星期格式 90 0 短名称 普通名称 长名称 英文名称 显示农历 true Qt::Horizontal 40 20 LunarCalendarWidget QWidget
lunarcalendarwidget.h
1
ukui-panel-3.0.6.4/ukui-calendar/lunarcalendarwidget/customstylePushbutton.cpp0000644000175000017500000002136614203402514026315 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * 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 3, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include CustomStyle_pushbutton::CustomStyle_pushbutton(const QString &proxyStyleName, QObject *parent) : QProxyStyle (proxyStyleName) { Q_UNUSED(parent); } void CustomStyle_pushbutton::drawComplexControl(QStyle::ComplexControl control, const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget) const { return QProxyStyle::drawComplexControl(control, option, painter, widget); } void CustomStyle_pushbutton::drawControl(QStyle::ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const { switch (element) { case QStyle::CE_PushButton: { QStyleOptionButton button = *qstyleoption_cast(option); button.palette.setColor(QPalette::HighlightedText, button.palette.buttonText().color()); return QProxyStyle::drawControl(element, &button, painter, widget); break; } default: break; } return QProxyStyle::drawControl(element, option, painter, widget); } void CustomStyle_pushbutton::drawItemPixmap(QPainter *painter, const QRect &rectangle, int alignment, const QPixmap &pixmap) const { return QProxyStyle::drawItemPixmap(painter, rectangle, alignment, pixmap); } void CustomStyle_pushbutton::drawItemText(QPainter *painter, const QRect &rectangle, int alignment, const QPalette &palette, bool enabled, const QString &text, QPalette::ColorRole textRole) const { return QProxyStyle::drawItemText(painter, rectangle, alignment, palette, enabled, text, textRole); } /// 我们重写button的绘制方法,通过state和当前动画的状态以及value值改变相关的绘制条件 /// 这里通过判断hover与否,动态的调整painter的透明度然后绘制背景 /// 需要注意的是,默认控件的绘制流程只会触发一次,而动画需要我们在一段时间内不停绘制才行, /// 要使得动画能够持续,我们需要使用QWidget::update()在动画未完成时, /// 手动更新一次,这样button将在一段时间后再次调用draw方法,从而达到更新动画的效果 /// /// 需要注意绘制背景的流程会因主题不同而产生差异,所以这一部分代码在一些主题中未必正常, /// 如果你需要自己实现一个主题,这同样是你需要注意和考虑的点 void CustomStyle_pushbutton::drawPrimitive(QStyle::PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const { // if (element == PE_PanelButtonCommand) { // qDebug()<<"draw pe button"; // if (widget) { // bool isPressed = false; // bool isHover = false; // if (!option->state.testFlag(State_Sunken)) { // if (option->state.testFlag(State_MouseOver)) { // isHover = true; // } // } else { // isPressed = true; // } // QStyleOption opt = *option; // if (isHover) { // QColor color(255,255,255,51); // opt.palette.setColor(QPalette::Highlight, color); // } // if (isPressed) { // QColor color(255,255,255,21); // opt.palette.setColor(QPalette::Highlight, color); // } // if (!isHover && !isPressed) { // QColor color(255,255,255,31); // opt.palette.setColor(QPalette::Button,color); // } // return QProxyStyle::drawPrimitive(element, &opt, painter, widget); // } // } // return QProxyStyle::drawPrimitive(element, option, painter, widget); if (element == PE_PanelButtonCommand) { if (widget) { if (option->state & State_MouseOver) { if (option->state & State_Sunken) { painter->save(); painter->setRenderHint(QPainter::Antialiasing,true); painter->setPen(Qt::NoPen); QColor color(255,255,255,21); painter->setBrush(color); painter->drawRoundedRect(option->rect, 4, 4); painter->restore(); } else { painter->save(); painter->setRenderHint(QPainter::Antialiasing,true); painter->setPen(Qt::NoPen); QColor color(255,255,255,51); painter->setBrush(color); painter->drawRoundedRect(option->rect, 4, 4); painter->restore(); } } else { painter->save(); painter->setRenderHint(QPainter::Antialiasing,true); painter->setPen(Qt::NoPen); QColor color(255,255,255,0); painter->setBrush(color); painter->drawRoundedRect(option->rect, 4, 4); painter->restore(); } return; } } return QProxyStyle::drawPrimitive(element, option, painter, widget); } QPixmap CustomStyle_pushbutton::generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap, const QStyleOption *option) const { return QProxyStyle::generatedIconPixmap(iconMode, pixmap, option); } QStyle::SubControl CustomStyle_pushbutton::hitTestComplexControl(QStyle::ComplexControl control, const QStyleOptionComplex *option, const QPoint &position, const QWidget *widget) const { return QProxyStyle::hitTestComplexControl(control, option, position, widget); } QRect CustomStyle_pushbutton::itemPixmapRect(const QRect &rectangle, int alignment, const QPixmap &pixmap) const { return QProxyStyle::itemPixmapRect(rectangle, alignment, pixmap); } QRect CustomStyle_pushbutton::itemTextRect(const QFontMetrics &metrics, const QRect &rectangle, int alignment, bool enabled, const QString &text) const { return QProxyStyle::itemTextRect(metrics, rectangle, alignment, enabled, text); } int CustomStyle_pushbutton::pixelMetric(QStyle::PixelMetric metric, const QStyleOption *option, const QWidget *widget) const { return QProxyStyle::pixelMetric(metric, option, widget); } /// 我们需要将动画与widget一一对应起来, /// 在一个style的生命周期里,widget只会进行polish和unpolish各一次, /// 所以我们可以在polish时将widget与一个新的动画绑定,并且对应的在unpolish中解绑定 void CustomStyle_pushbutton::polish(QWidget *widget) { return QProxyStyle::polish(widget); } void CustomStyle_pushbutton::polish(QApplication *application) { return QProxyStyle::polish(application); } void CustomStyle_pushbutton::polish(QPalette &palette) { return QProxyStyle::polish(palette); } void CustomStyle_pushbutton::unpolish(QWidget *widget) { return QProxyStyle::unpolish(widget); } void CustomStyle_pushbutton::unpolish(QApplication *application) { return QProxyStyle::unpolish(application); } QSize CustomStyle_pushbutton::sizeFromContents(QStyle::ContentsType type, const QStyleOption *option, const QSize &contentsSize, const QWidget *widget) const { return QProxyStyle::sizeFromContents(type, option, contentsSize, widget); } QIcon CustomStyle_pushbutton::standardIcon(QStyle::StandardPixmap standardIcon, const QStyleOption *option, const QWidget *widget) const { return QProxyStyle::standardIcon(standardIcon, option, widget); } QPalette CustomStyle_pushbutton::standardPalette() const { return QProxyStyle::standardPalette(); } int CustomStyle_pushbutton::styleHint(QStyle::StyleHint hint, const QStyleOption *option, const QWidget *widget, QStyleHintReturn *returnData) const { return QProxyStyle::styleHint(hint, option, widget, returnData); } QRect CustomStyle_pushbutton::subControlRect(QStyle::ComplexControl control, const QStyleOptionComplex *option, QStyle::SubControl subControl, const QWidget *widget) const { return QProxyStyle::subControlRect(control, option, subControl, widget); } QRect CustomStyle_pushbutton::subElementRect(QStyle::SubElement element, const QStyleOption *option, const QWidget *widget) const { return QProxyStyle::subElementRect(element, option, widget); } ukui-panel-3.0.6.4/ukui-calendar/lunarcalendarwidget/statelabel.h0000644000175000017500000000204614203402514023405 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include class statelabel : public QLabel { Q_OBJECT public: statelabel(); protected: void mousePressEvent(QMouseEvent *event); Q_SIGNALS : void labelclick(); }; #endif // STATELABEL_H ukui-panel-3.0.6.4/ukui-calendar/lunarcalendarwidget/picturetowhite.h0000644000175000017500000000307214203402514024344 0ustar fengfeng/* * Copyright (C) 2020 Tianjin KYLIN Information Technology Co., Ltd. * * 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 3, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include #include #define ORG_UKUI_STYLE "org.ukui.style" #define STYLE_NAME "styleName" #define STYLE_NAME_KEY_DARK "ukui-dark" #define STYLE_NAME_KEY_DEFAULT "ukui-default" #define STYLE_NAME_KEY_BLACK "ukui-black" #define STYLE_NAME_KEY_LIGHT "ukui-light" #define STYLE_NAME_KEY_WHITE "ukui-white" #define TRAY_ICON_COLOR_LOGHT 0 #define TRAY_ICON_COLOR_DRAK 255 class PictureToWhite : public QObject { Q_OBJECT public: explicit PictureToWhite(QObject *parent = nullptr); void initGsettingValue(); QPixmap drawSymbolicColoredPixmap(const QPixmap &source); public: QGSettings *m_pgsettings; int tray_icon_color; }; #endif // PICTURETOWHITE_H ukui-panel-3.0.6.4/ukui-calendar/lunarcalendarwidget/lunarcalendarwidget.cpp0000644000175000017500000013673714203402514025656 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #define PANEL_CONTROL_IN_CALENDAR "org.ukui.control-center.panel.plugins" #define LUNAR_KEY "calendar" #define FIRST_DAY_KEY "firstday" #define ORG_UKUI_STYLE "org.ukui.style" #define STYLE_NAME "styleName" #define STYLE_NAME_KEY_DARK "ukui-dark" #define STYLE_NAME_KEY_DEFAULT "ukui-default" #define STYLE_NAME_KEY_BLACK "ukui-black" #define STYLE_NAME_KEY_LIGHT "ukui-light" #define STYLE_NAME_KEY_WHITE "ukui-white" #define ICON_COLOR_LOGHT 255 #define ICON_COLOR_DRAK 0 LunarCalendarWidget::LunarCalendarWidget(QWidget *parent) : QWidget(parent) { analysisWorktimeJs(); const QByteArray calendar_id(PANEL_CONTROL_IN_CALENDAR); if(QGSettings::isSchemaInstalled(calendar_id)){ calendar_gsettings = new QGSettings(calendar_id); //农历切换监听与日期显示格式 connect(calendar_gsettings, &QGSettings::changed, this, [=] (const QString &key){ if(key == LUNAR_KEY){ if(calendar_gsettings->get("calendar").toString() == "lunar") { //农历 lunarstate = true; labWidget->setVisible(true); yijiWidget->setVisible(true); } else { //公历 lunarstate = false; labWidget->setVisible(false); yijiWidget->setVisible(false); } _timeUpdate(); } if(key == "date") { if(calendar_gsettings->get("date").toString() == "cn"){ dateShowMode = "yyyy/MM/dd dddd"; } else { dateShowMode = "yyyy-MM-dd dddd"; } } }); if(calendar_gsettings->get("date").toString() == "cn"){ dateShowMode = "yyyy/MM/dd dddd"; } else { dateShowMode = "yyyy-MM-dd dddd"; } //监听12/24小时制 connect(calendar_gsettings, &QGSettings::changed, this, [=] (const QString &keys){ timemodel = calendar_gsettings->get("hoursystem").toString(); _timeUpdate(); }); timemodel = calendar_gsettings->get("hoursystem").toString(); } else { dateShowMode = "yyyy/MM/dd dddd"; //无设置默认公历 lunarstate = true; } setWindowOpacity(0.7); setAttribute(Qt::WA_TranslucentBackground);//设置窗口背景透明 setProperty("useSystemStyleBlur", true); //设置毛玻璃效果 //判断图形字体是否存在,不存在则加入 QFontDatabase fontDb; if (!fontDb.families().contains("FontAwesome")) { int fontId = fontDb.addApplicationFont(":/image/fontawesome-webfont.ttf"); QStringList fontName = fontDb.applicationFontFamilies(fontId); if (fontName.count() == 0) { qDebug() << "load fontawesome-webfont.ttf error"; } } if (fontDb.families().contains("FontAwesome")) { iconFont = QFont("FontAwesome"); #if (QT_VERSION >= QT_VERSION_CHECK(4,8,0)) iconFont.setHintingPreference(QFont::PreferNoHinting); #endif } btnYear = new QPushButton; btnMonth = new QPushButton; btnToday = new QPushButton; btnClick = false; calendarStyle = CalendarStyle_Red; date = QDate::currentDate(); widgetTime = new QWidget; timeShow = new QVBoxLayout(widgetTime); datelabel =new QLabel(this); timelabel = new QLabel(this); lunarlabel = new QLabel(this); widgetTime->setObjectName("widgetTime"); timeShow->setContentsMargins(0, 0, 0, 0); initWidget(); if(QGSettings::isSchemaInstalled(calendar_id)){ //初始化农历/公历显示方式 if(calendar_gsettings->get("calendar").toString() == "lunar") { //农历 lunarstate = true; labWidget->setVisible(true); yijiWidget->setVisible(true); } else { //公历 lunarstate = false; labWidget->setVisible(false); yijiWidget->setVisible(false); } } //切换主题 const QByteArray style_id(ORG_UKUI_STYLE); QStringList stylelist; stylelist<get(STYLE_NAME).toString()); setColor(dark_style); } connect(style_settings, &QGSettings::changed, this, [=] (const QString &key){ if(key==STYLE_NAME){ dark_style=stylelist.contains(style_settings->get(STYLE_NAME).toString()); _timeUpdate(); setColor(dark_style); QPixmap pixmap1 = QIcon::fromTheme("strIconPath", QIcon::fromTheme("pan-up-symbolic")).pixmap(QSize(24, 24)); PictureToWhite pictToWhite1; btnPrevYear->setPixmap(pictToWhite1.drawSymbolicColoredPixmap(pixmap1)); btnPrevYear->setProperty("useIconHighlightEffect", 0x2); QPixmap pixmap2 = QIcon::fromTheme("strIconPath", QIcon::fromTheme("pan-down-symbolic")).pixmap(QSize(24, 24)); PictureToWhite pictToWhite2; btnNextYear->setPixmap(pictToWhite2.drawSymbolicColoredPixmap(pixmap2)); btnNextYear->setProperty("useIconHighlightEffect", 0x2); } }); // //实时监听系统字体的改变 // const QByteArray id("org.ukui.style"); // QGSettings * fontSetting = new QGSettings(id, QByteArray(), this); // connect(fontSetting, &QGSettings::changed,[=](QString key) { // if ("systemFont" == key || "systemFontSize" ==key) { // QFont font = this->font(); // btnToday->setFont(font); // cboxYearandMonth->setFont(font); // for (int i = 0; i < 42; i++) { // dayItems.value(i)->setFont(font); // dayItems.value(i)->repaint(); // } // for (int i = 0; i < 7; i++) { // labWeeks.value(i)->setFont(font); // labWeeks.value(i)->repaint(); // } // } // }); timer = new QTimer(); connect(timer,SIGNAL(timeout()),this,SLOT(timerUpdate())); timer->start(1000); if(QGSettings::isSchemaInstalled(calendar_id)){ setWeekNameFormat(calendar_gsettings->get(FIRST_DAY_KEY).toString() == "sunday"); setShowLunar(calendar_gsettings->get(LUNAR_KEY).toString() == "lunar"); } } LunarCalendarWidget::~LunarCalendarWidget() { } bool LunarCalendarWidget::eventFilter(QObject *obj, QEvent *event) { if (event->type() == QEvent::ActivationChange) { qDebug()<<"event->type() == QEvent::ActivationChange"; if(QApplication::activeWindow() != this) { qDebug()<<"this->hide()"; this->hide(); } } return QWidget::event(event); } /* * @brief 设置日历的背景及文字颜色 * 参数: * weekColor 周六及周日文字颜色 */ void LunarCalendarWidget::setColor(bool mdark_style) { const QByteArray calendar_id(PANEL_CONTROL_IN_CALENDAR); if(mdark_style){ weekTextColor = QColor(0, 0, 0); weekBgColor = QColor(180, 180, 180); if(QGSettings::isSchemaInstalled(calendar_id)){ showLunar = calendar_gsettings->get(LUNAR_KEY).toString() == "lunar"; } bgImage = ":/image/bg_calendar.png"; selectType = SelectType_Rect; borderColor = QColor(180, 180, 180); weekColor = QColor(255, 255, 255); superColor = QColor(255, 129, 6); lunarColor = QColor(233, 90, 84); currentTextColor = QColor(255, 255, 255); otherTextColor = QColor(125, 125, 125); selectTextColor = QColor(255, 255, 255); hoverTextColor = QColor(0, 0, 0); currentLunarColor = QColor(150, 150, 150); otherLunarColor = QColor(200, 200, 200); selectLunarColor = QColor(255, 255, 255); hoverLunarColor = QColor(250, 250, 250); currentBgColor = QColor(0, 0, 0); otherBgColor = QColor(240, 240, 240); selectBgColor = QColor(80, 100, 220); hoverBgColor = QColor(80, 190, 220); }else{ weekTextColor = QColor(255, 255, 255); weekBgColor = QColor(0, 0, 0); if(QGSettings::isSchemaInstalled(calendar_id)){ showLunar = calendar_gsettings->get(LUNAR_KEY).toString() == "lunar"; } bgImage = ":/image/bg_calendar.png"; selectType = SelectType_Rect; borderColor = QColor(180, 180, 180); weekColor = QColor(0, 0, 0); superColor = QColor(255, 129, 6); lunarColor = QColor(233, 90, 84); currentTextColor = QColor(0, 0, 0); otherTextColor = QColor(125, 125, 125); selectTextColor = QColor(255, 255, 255); hoverTextColor = QColor(0, 0, 0); currentLunarColor = QColor(150, 150, 150); otherLunarColor = QColor(200, 200, 200); selectLunarColor = QColor(255, 255, 255); hoverLunarColor = QColor(250, 250, 250); currentBgColor = QColor(250, 250, 250); otherBgColor = QColor(240, 240, 240); selectBgColor = QColor(80, 100, 220); hoverBgColor = QColor(80, 190, 220); } initStyle(); } void LunarCalendarWidget::_timeUpdate() { QDateTime time = QDateTime::currentDateTime(); QLocale locale = (QLocale::system().name() == "zh_CN" ? (QLocale::Chinese) : (QLocale::English)); QString _time; if(timemodel == "12") { _time = locale.toString(time,"Ahh:mm:ss"); } else { _time = locale.toString(time,"hh:mm:ss"); } QFont font; datelabel->setText(_time); font.setPointSize(22); datelabel->setFont(font); datelabel->setAlignment(Qt::AlignHCenter); QString strHoliday; QString strSolarTerms; QString strLunarFestival; QString strLunarYear; QString strLunarMonth; QString strLunarDay; LunarCalendarInfo::Instance()->getLunarCalendarInfo(locale.toString(time,"yyyy").toInt(), locale.toString(time,"MM").toInt(), locale.toString(time,"dd").toInt(), strHoliday, strSolarTerms, strLunarFestival, strLunarYear, strLunarMonth, strLunarDay); QString _date = locale.toString(time,dateShowMode); if (lunarstate) { _date = _date + " "+strLunarMonth + strLunarDay; } timelabel->setText(_date); font.setPointSize(12); timelabel->setFont(font); timelabel->setAlignment(Qt::AlignHCenter); } void LunarCalendarWidget::timerUpdate() { _timeUpdate(); } void LunarCalendarWidget::initWidget() { setObjectName("lunarCalendarWidget"); //顶部widget QWidget *widgetTop = new QWidget; widgetTop->setObjectName("widgetTop"); widgetTop->setMinimumHeight(35); //上个月的按钮 btnPrevYear = new statelabel; btnPrevYear->setObjectName("btnPrevYear"); btnPrevYear->setFixedWidth(35); btnPrevYear->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding); QPixmap pixmap1 = QIcon::fromTheme("strIconPath", QIcon::fromTheme("pan-up-symbolic")).pixmap(QSize(24, 24)); PictureToWhite pictToWhite1; btnPrevYear->setPixmap(pictToWhite1.drawSymbolicColoredPixmap(pixmap1)); btnPrevYear->setProperty("useIconHighlightEffect", 0x2); //下个月按钮 btnNextYear = new statelabel; btnNextYear->setObjectName("btnNextYear"); btnNextYear->setFixedWidth(35); btnNextYear->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding); QPixmap pixmap2 = QIcon::fromTheme("strIconPath", QIcon::fromTheme("pan-down-symbolic")).pixmap(QSize(24, 24)); PictureToWhite pictToWhite2; btnNextYear->setPixmap(pictToWhite2.drawSymbolicColoredPixmap(pixmap2)); btnNextYear->setProperty("useIconHighlightEffect", 0x2); //转到年显示 btnYear->setObjectName("btnYear"); btnYear->setFocusPolicy(Qt::NoFocus); btnYear->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding); QTimer::singleShot(0,this,[=]{ btnYear->setText(tr("Year")); }); btnYear->setStyle(new CustomStyle_pushbutton("ukui-default")); connect(btnYear,&QPushButton::clicked,this,&LunarCalendarWidget::yearWidgetChange); //转到月显示 btnMonth->setObjectName("btnMonth"); btnMonth->setFocusPolicy(Qt::NoFocus); btnMonth->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding); QTimer::singleShot(0,this,[=]{ btnMonth->setText(tr("Month")); }); btnMonth->setStyle(new CustomStyle_pushbutton("ukui-default")); connect(btnMonth,&QPushButton::clicked,this,&LunarCalendarWidget::monthWidgetChange); //转到今天 btnToday->setObjectName("btnToday"); btnToday->setFocusPolicy(Qt::NoFocus); //btnToday->setFixedWidth(40); btnToday->setStyle(new CustomStyle_pushbutton("ukui-default")); btnToday->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding); QTimer::singleShot(0,this,[=]{ btnToday->setText(tr("Today")); }); //年份与月份下拉框 暂不用此 cboxYearandMonth = new QComboBox; cboxYearandMonth->setStyleSheet("QComboBox{background: transparent;font-size: 20px;}" "QComboBox::down-down{width: 1px;}"); cboxYearandMonth->setFixedWidth(100); cboxYearandMonth->setObjectName("cboxYearandMonth"); for (int i = 1901; i <= 2099; i++) { for (int j = 1; j <= 12; j++) { cboxYearandMonth->addItem(QString("%1.%2").arg(i).arg(j)); } } cboxYearandMonthLabel = new QLabel(); cboxYearandMonthLabel->setFixedWidth(100); //中间用个空widget隔开 // QWidget *widgetBlank1 = new QWidget; // widgetBlank1->setFixedWidth(180); // QWidget *widgetBlank2 = new QWidget; // widgetBlank2->setFixedWidth(5); // QWidget *widgetBlank3 = new QWidget; // widgetBlank3->setFixedWidth(40); //顶部横向布局 QHBoxLayout *layoutTop = new QHBoxLayout(widgetTop); layoutTop->setContentsMargins(0, 0, 0, 9); layoutTop->addItem(new QSpacerItem(5,1)); layoutTop->addWidget(cboxYearandMonthLabel); layoutTop->addStretch(); layoutTop->addWidget(btnNextYear); layoutTop->addWidget(btnPrevYear); layoutTop->addStretch(); layoutTop->addWidget(btnYear); layoutTop->addWidget(btnMonth); layoutTop->addWidget(btnToday); layoutTop->addStretch(); layoutTop->addItem(new QSpacerItem(10,1)); //时间 widgetTime->setMinimumHeight(50); timeShow->addWidget(datelabel);//, Qt::AlignHCenter); timeShow->addWidget(timelabel);//,Qt::AlignHCenter); //星期widget widgetWeek = new QWidget; widgetWeek->setObjectName("widgetWeek"); widgetWeek->setMinimumHeight(30); //星期布局 QHBoxLayout *layoutWeek = new QHBoxLayout(widgetWeek); layoutWeek->setMargin(0); layoutWeek->setSpacing(0); for (int i = 0; i < 7; i++) { QLabel *lab = new QLabel; lab->setAlignment(Qt::AlignCenter); layoutWeek->addWidget(lab); labWeeks.append(lab); } //日期标签widget widgetDayBody = new QWidget; widgetDayBody->setObjectName("widgetDayBody"); //日期标签布局 QGridLayout *layoutBodyDay = new QGridLayout(widgetDayBody); layoutBodyDay->setMargin(1); layoutBodyDay->setHorizontalSpacing(0); layoutBodyDay->setVerticalSpacing(0); //逐个添加日标签 for (int i = 0; i < 42; i++) { LunarCalendarItem *lab = new LunarCalendarItem; lab->worktime = worktime; connect(lab, SIGNAL(clicked(QDate, LunarCalendarItem::DayType)), this, SLOT(clicked(QDate, LunarCalendarItem::DayType))); layoutBodyDay->addWidget(lab, i / 7, i % 7); dayItems.append(lab); } //年份标签widget widgetYearBody = new QWidget; widgetYearBody->setObjectName("widgetYearBody"); //年份标签布局 QGridLayout *layoutBodyYear = new QGridLayout(widgetYearBody); layoutBodyYear->setMargin(1); layoutBodyYear->setHorizontalSpacing(0); layoutBodyYear->setVerticalSpacing(0); //逐个添加年标签 for (int i = 0; i < 12; i++) { LunarCalendarYearItem *labYear = new LunarCalendarYearItem; connect(labYear, SIGNAL(yearMessage(QDate, LunarCalendarYearItem::DayType)), this, SLOT(updateYearClicked(QDate, LunarCalendarYearItem::DayType))); layoutBodyYear->addWidget(labYear, i / 3, i % 3); yearItems.append(labYear); } widgetYearBody->hide(); //月份标签widget widgetmonthBody = new QWidget; widgetmonthBody->setObjectName("widgetmonthBody"); //月份标签布局 QGridLayout *layoutBodyMonth = new QGridLayout(widgetmonthBody); layoutBodyMonth->setMargin(1); layoutBodyMonth->setHorizontalSpacing(0); layoutBodyMonth->setVerticalSpacing(0); //逐个添加月标签 for (int i = 0; i < 12; i++) { LunarCalendarMonthItem *labMonth = new LunarCalendarMonthItem; connect(labMonth, SIGNAL(monthMessage(QDate, LunarCalendarMonthItem::DayType)), this, SLOT(updateMonthClicked(QDate, LunarCalendarMonthItem::DayType))); layoutBodyMonth->addWidget(labMonth, i / 3, i % 3); monthItems.append(labMonth); } widgetmonthBody->hide(); labWidget = new QWidget(); labBottom = new QLabel(); yijichooseLabel = new QLabel(); yijichooseLabel->setText("宜忌"); QFont font; font.setPointSize(12); labBottom->setFont(font); yijichoose = new QCheckBox(); labLayout = new QHBoxLayout(); labLayout->addWidget(labBottom); labLayout->addItem(new QSpacerItem(100,5,QSizePolicy::Expanding,QSizePolicy::Minimum)); labLayout->addWidget(yijichooseLabel); labLayout->addWidget(yijichoose); labWidget->setLayout(labLayout); yijiLayout = new QVBoxLayout; yijiWidget = new QWidget; // yijiWidget->setFixedHeight(60); yiLabel = new QLabel(); jiLabel = new QLabel(); yijiLayout->addWidget(yiLabel); yijiLayout->addWidget(jiLabel); yijiWidget->setLayout(yijiLayout); yiLabel->setVisible(false); jiLabel->setVisible(false); connect(yijichoose,&QRadioButton::clicked,this,&LunarCalendarWidget::customButtonsClicked); //主布局 lineUp = new m_PartLineWidget(); lineDown = new m_PartLineWidget(); lineUp->setFixedSize(440, 1); lineDown->setFixedSize(440, 1); QVBoxLayout *verLayoutCalendar = new QVBoxLayout(this); verLayoutCalendar->setMargin(0); verLayoutCalendar->setSpacing(0); verLayoutCalendar->addWidget(widgetTime); // QTimer::singleShot(0,this,[=](){ // }); verLayoutCalendar->addItem(new QSpacerItem(10,10)); verLayoutCalendar->addWidget(lineUp); verLayoutCalendar->addItem(new QSpacerItem(10,10)); verLayoutCalendar->addWidget(widgetTop); verLayoutCalendar->addWidget(widgetWeek); verLayoutCalendar->addWidget(widgetDayBody, 1); verLayoutCalendar->addWidget(widgetYearBody, 1); verLayoutCalendar->addWidget(widgetmonthBody, 1); verLayoutCalendar->addWidget(lineDown); verLayoutCalendar->addWidget(labWidget); verLayoutCalendar->addWidget(yijiWidget); //绑定按钮和下拉框信号 // connect(btnPrevYear, SIGNAL(clicked(bool)), this, SLOT(showPreviousYear())); // connect(btnNextYear, SIGNAL(clicked(bool)), this, SLOT(showNextYear())); connect(btnPrevYear, SIGNAL(labelclick()), this, SLOT(showPreviousMonth())); connect(btnNextYear, SIGNAL(labelclick()), this, SLOT(showNextMonth())); connect(btnToday, SIGNAL(clicked(bool)), this, SLOT(showToday())); connect(cboxYearandMonth, SIGNAL(currentIndexChanged(QString)), this, SLOT(yearChanged(QString))); // connect(cboxMonth, SIGNAL(currentIndexChanged(QString)), this, SLOT(monthChanged(QString))); } void LunarCalendarWidget::initStyle() { //设置样式 QStringList qss; //自定义日控件颜色 QString strSelectType; if (selectType == SelectType_Rect) { strSelectType = "SelectType_Rect"; } else if (selectType == SelectType_Circle) { strSelectType = "SelectType_Circle"; } else if (selectType == SelectType_Triangle) { strSelectType = "SelectType_Triangle"; } else if (selectType == SelectType_Image) { strSelectType = "SelectType_Image"; } //计划去掉qss,保留农历切换的设置 qss.append(QString("LunarCalendarItem{qproperty-showLunar:%1;}").arg(showLunar)); this->setStyleSheet(qss.join("")); } void LunarCalendarWidget::analysisWorktimeJs() { /*解析json文件*/ QFile file("/usr/share/ukui-panel/plugin-calendar/html/jiejiari.js"); file.open(QIODevice::ReadOnly | QIODevice::Text); QString value = file.readAll(); file.close(); QJsonParseError parseJsonErr; QJsonDocument document = QJsonDocument::fromJson(value.toUtf8(),&parseJsonErr); if(!(parseJsonErr.error == QJsonParseError::NoError)) { qDebug()<isHidden()){ widgetYearBody->show(); widgetWeek->hide(); widgetDayBody->hide(); widgetmonthBody->hide(); } else{ widgetYearBody->hide(); widgetWeek->show(); widgetDayBody->show(); widgetmonthBody->hide(); } } void LunarCalendarWidget::monthWidgetChange() { if(widgetmonthBody->isHidden()){ widgetYearBody->hide(); widgetWeek->hide(); widgetDayBody->hide(); widgetmonthBody->show(); } else{ widgetYearBody->hide(); widgetWeek->show(); widgetDayBody->show(); widgetmonthBody->hide(); } } //初始化日期面板 void LunarCalendarWidget::initDate() { int year = date.year(); int month = date.month(); int day = date.day(); if(oneRun) { downLabelHandle(date); yijihandle(date); oneRun = false; } //设置为今天,设置变量防止重复触发 btnClick = true; cboxYearandMonth->setCurrentIndex(cboxYearandMonth->findText(QString("%1.%2").arg(year).arg(month))); btnClick = false; cboxYearandMonthLabel->setText(QString(" %1.%2").arg(year).arg(month)); //首先判断当前月的第一天是星期几 int week = LunarCalendarInfo::Instance()->getFirstDayOfWeek(year, month, FirstdayisSun); //当前月天数 int countDay = LunarCalendarInfo::Instance()->getMonthDays(year, month); //上月天数 int countDayPre = LunarCalendarInfo::Instance()->getMonthDays(1 == month ? year - 1 : year, 1 == month ? 12 : month - 1); //如果上月天数上月刚好一周则另外处理 int startPre, endPre, startNext, endNext, index, tempYear, tempMonth, tempDay; if (0 == week) { startPre = 0; endPre = 7; startNext = 0; endNext = 42 - (countDay + 7); } else { startPre = 0; endPre = week; startNext = week + countDay; endNext = 42; } //纠正1月份前面部分偏差,1月份前面部分是上一年12月份 tempYear = year; tempMonth = month - 1; if (tempMonth < 1) { tempYear--; tempMonth = 12; } //显示上月天数 for (int i = startPre; i < endPre; i++) { index = i; tempDay = countDayPre - endPre + i + 1; QDate date(tempYear, tempMonth, tempDay); QString lunar = LunarCalendarInfo::Instance()->getLunarDay(tempYear, tempMonth, tempDay); dayItems.at(index)->setDate(date, lunar, LunarCalendarItem::DayType_MonthPre); } //纠正12月份后面部分偏差,12月份后面部分是下一年1月份 tempYear = year; tempMonth = month + 1; if (tempMonth > 12) { tempYear++; tempMonth = 1; } //显示下月天数 for (int i = startNext; i < endNext; i++) { index = 42 - endNext + i; tempDay = i - startNext + 1; QDate date(tempYear, tempMonth, tempDay); QString lunar = LunarCalendarInfo::Instance()->getLunarDay(tempYear, tempMonth, tempDay); dayItems.at(index)->setDate(date, lunar, LunarCalendarItem::DayType_MonthNext); } //重新置为当前年月 tempYear = year; tempMonth = month; //显示当前月 for (int i = week; i < (countDay + week); i++) { index = (0 == week ? (i + 7) : i); tempDay = i - week + 1; QDate date(tempYear, tempMonth, tempDay); QString lunar = LunarCalendarInfo::Instance()->getLunarDay(tempYear, tempMonth, tempDay); if (0 == (i % 7) || 6 == (i % 7)) { dayItems.at(index)->setDate(date, lunar, LunarCalendarItem::DayType_WeekEnd); } else { dayItems.at(index)->setDate(date, lunar, LunarCalendarItem::DayType_MonthCurrent); } } for (int i=0;i<12;i++){ yearItems.at(i)->setDate(date.addYears(i)); monthItems.at(i)->setDate(date.addMonths(i)); } } void LunarCalendarWidget::customButtonsClicked(int x) { if (x) { yiLabel->setVisible(true); jiLabel->setVisible(true); yijistate = true; Q_EMIT yijiChangeUp(); } else { yiLabel->setVisible(false); jiLabel->setVisible(false); Q_EMIT yijiChangeDown(); yijistate = false; } } QString LunarCalendarWidget::getSettings() { QString arg = "配置文件"; return arg; } void LunarCalendarWidget::setSettings(QString arg) { } void LunarCalendarWidget::downLabelHandle(const QDate &date) { QString strHoliday; QString strSolarTerms; QString strLunarFestival; QString strLunarYear; QString strLunarMonth; QString strLunarDay; LunarCalendarInfo::Instance()->getLunarCalendarInfo(date.year(), date.month(), date.day(), strHoliday, strSolarTerms, strLunarFestival, strLunarYear, strLunarMonth, strLunarDay); QString labBottomarg = " " + strLunarYear + " " + strLunarMonth + strLunarDay; labBottom->setText(labBottomarg); } void LunarCalendarWidget::yijihandle(const QDate &date) { /*解析json文件*/ QFile file(QString("/usr/share/ukui-panel/plugin-calendar/html/hlnew/hl%1.js").arg(date.year())); file.open(QIODevice::ReadOnly | QIODevice::Text); QString value = file.readAll(); file.close(); QJsonParseError parseJsonErr; QJsonDocument document = QJsonDocument::fromJson(value.toUtf8(),&parseJsonErr); if(!(parseJsonErr.error == QJsonParseError::NoError)) { qDebug()<setText(yiString); jiLabel->setText(jiString); } } void LunarCalendarWidget::yearChanged(const QString &arg1) { //如果是单击按钮切换的日期变动则不需要触发 if (btnClick) { return; } int nIndex = arg1.indexOf("."); if(-1 == nIndex){ return; } int year = arg1.mid(0,nIndex).toInt(); int month = arg1.mid(nIndex + 1).toInt(); int day = date.day(); dateChanged(year, month, day); } void LunarCalendarWidget::monthChanged(const QString &arg1) { //如果是单击按钮切换的日期变动则不需要触发 if (btnClick) { return; } int year = date.year(); int month = arg1.mid(0, arg1.length()).toInt(); int day = date.day(); dateChanged(year, month, day); } void LunarCalendarWidget::clicked(const QDate &date, const LunarCalendarItem::DayType &dayType) { this->date = date; clickDate = date; dayChanged(this->date,clickDate); if (LunarCalendarItem::DayType_MonthPre == dayType) showPreviousMonth(false); else if (LunarCalendarItem::DayType_MonthNext == dayType) showNextMonth(false); } void LunarCalendarWidget::updateYearClicked(const QDate &date, const LunarCalendarYearItem::DayType &dayType) { //通过传来的日期,设置当前年月份 widgetYearBody->hide(); widgetWeek->show(); widgetDayBody->show(); widgetmonthBody->hide(); // qDebug()<<"year:::::::::::::::::::::"<date; // } } void LunarCalendarWidget::updateMonthClicked(const QDate &date, const LunarCalendarMonthItem::DayType &dayType) { //通过传来的日期,设置当前年月份 widgetYearBody->hide(); widgetWeek->show(); widgetDayBody->show(); widgetmonthBody->hide(); qDebug()<setCurrentIndex(cboxYearandMonth->findText(QString("%1.%2").arg(year).arg(month))); btnClick = false; cboxYearandMonthLabel->setText(QString(" %1.%2").arg(year).arg(month)); //首先判断当前月的第一天是星期几 int week = LunarCalendarInfo::Instance()->getFirstDayOfWeek(year, month, FirstdayisSun); //当前月天数 int countDay = LunarCalendarInfo::Instance()->getMonthDays(year, month); //上月天数 int countDayPre = LunarCalendarInfo::Instance()->getMonthDays(1 == month ? year - 1 : year, 1 == month ? 12 : month - 1); //如果上月天数上月刚好一周则另外处理 int startPre, endPre, startNext, endNext, index, tempYear, tempMonth, tempDay; if (0 == week) { startPre = 0; endPre = 7; startNext = 0; endNext = 42 - (countDay + 7); } else { startPre = 0; endPre = week; startNext = week + countDay; endNext = 42; } //纠正1月份前面部分偏差,1月份前面部分是上一年12月份 tempYear = year; tempMonth = month - 1; if (tempMonth < 1) { tempYear--; tempMonth = 12; } //显示上月天数 for (int i = startPre; i < endPre; i++) { index = i; tempDay = countDayPre - endPre + i + 1; QDate date(tempYear, tempMonth, tempDay); QString lunar = LunarCalendarInfo::Instance()->getLunarDay(tempYear, tempMonth, tempDay); dayItems.at(index)->setDate(date, lunar, LunarCalendarItem::DayType_MonthPre); } //纠正12月份后面部分偏差,12月份后面部分是下一年1月份 tempYear = year; tempMonth = month + 1; if (tempMonth > 12) { tempYear++; tempMonth = 1; } //显示下月天数 for (int i = startNext; i < endNext; i++) { index = 42 - endNext + i; tempDay = i - startNext + 1; QDate date(tempYear, tempMonth, tempDay); QString lunar = LunarCalendarInfo::Instance()->getLunarDay(tempYear, tempMonth, tempDay); dayItems.at(index)->setDate(date, lunar, LunarCalendarItem::DayType_MonthNext); } //重新置为当前年月 tempYear = year; tempMonth = month; //显示当前月 for (int i = week; i < (countDay + week); i++) { index = (0 == week ? (i + 7) : i); tempDay = i - week + 1; QDate date(tempYear, tempMonth, tempDay); QString lunar = LunarCalendarInfo::Instance()->getLunarDay(tempYear, tempMonth, tempDay); if (0 == (i % 7) || 6 == (i % 7)) { dayItems.at(index)->setDate(date, lunar, LunarCalendarItem::DayType_WeekEnd); } else { dayItems.at(index)->setDate(date, lunar, LunarCalendarItem::DayType_MonthCurrent); } } for (int i=0;i<12;i++){ yearItems.at(i)->setDate(clickDate.addYears(i)); // qDebug()<<"*******************"<<"循环位:"<setDate(clickDate.addMonths(i)); } } void LunarCalendarWidget::dayChanged(const QDate &date,const QDate &m_date) { //计算星期几,当前天对应标签索引=日期+星期几-1 int year = date.year(); int month = date.month(); int day = date.day(); int week = LunarCalendarInfo::Instance()->getFirstDayOfWeek(year, month, FirstdayisSun); //选中当前日期,其他日期恢复,这里还有优化空间,比方说类似单选框机制 for (int i = 0; i < 42; i++) { //当月第一天是星期天要另外计算 int index = day + week - 1; if (week == 0) { index = day + 6; } dayItems.at(i)->setSelect(false); if(dayItems.at(i)->getDate() == m_date) { dayItems.at(i)->setSelect(i == index); } if (i == index) { downLabelHandle(dayItems.at(i)->getDate()); yijihandle(dayItems.at(i)->getDate()); } } //发送日期单击信号 Q_EMIT clicked(date); //发送日期更新信号 Q_EMIT selectionChanged(); } void LunarCalendarWidget::dateChanged(int year, int month, int day) { //如果原有天大于28则设置为1,防止出错 date.setDate(year, month, day > 28 ? 1 : day); initDate(); } LunarCalendarWidget::CalendarStyle LunarCalendarWidget::getCalendarStyle() const { return this->calendarStyle; } QDate LunarCalendarWidget::getDate() const { return this->date; } QColor LunarCalendarWidget::getWeekTextColor() const { return this->weekTextColor; } QColor LunarCalendarWidget::getWeekBgColor() const { return this->weekBgColor; } bool LunarCalendarWidget::getShowLunar() const { return this->showLunar; } QString LunarCalendarWidget::getBgImage() const { return this->bgImage; } LunarCalendarWidget::SelectType LunarCalendarWidget::getSelectType() const { return this->selectType; } QColor LunarCalendarWidget::getBorderColor() const { return this->borderColor; } QColor LunarCalendarWidget::getWeekColor() const { return this->weekColor; } QColor LunarCalendarWidget::getSuperColor() const { return this->superColor; } QColor LunarCalendarWidget::getLunarColor() const { return this->lunarColor; } QColor LunarCalendarWidget::getCurrentTextColor() const { return this->currentTextColor; } QColor LunarCalendarWidget::getOtherTextColor() const { return this->otherTextColor; } QColor LunarCalendarWidget::getSelectTextColor() const { return this->selectTextColor; } QColor LunarCalendarWidget::getHoverTextColor() const { return this->hoverTextColor; } QColor LunarCalendarWidget::getCurrentLunarColor() const { return this->currentLunarColor; } QColor LunarCalendarWidget::getOtherLunarColor() const { return this->otherLunarColor; } QColor LunarCalendarWidget::getSelectLunarColor() const { return this->selectLunarColor; } QColor LunarCalendarWidget::getHoverLunarColor() const { return this->hoverLunarColor; } QColor LunarCalendarWidget::getCurrentBgColor() const { return this->currentBgColor; } QColor LunarCalendarWidget::getOtherBgColor() const { return this->otherBgColor; } QColor LunarCalendarWidget::getSelectBgColor() const { return this->selectBgColor; } QColor LunarCalendarWidget::getHoverBgColor() const { return this->hoverBgColor; } QSize LunarCalendarWidget::sizeHint() const { return QSize(600, 500); } QSize LunarCalendarWidget::minimumSizeHint() const { return QSize(200, 150); } //显示上一年 void LunarCalendarWidget::showPreviousYear() { int year = date.year(); int month = date.month(); int day = date.day(); if (year <= 1901) { return; } year--; dateChanged(year, month, day); } //显示下一年 void LunarCalendarWidget::showNextYear() { int year = date.year(); int month = date.month(); int day = date.day(); if (year >= 2099) { return; } year++; dateChanged(year, month, day); } //显示上月日期 void LunarCalendarWidget::showPreviousMonth(bool date_clicked) { int year = date.year(); int month = date.month(); int day = date.day(); if (year <= 1901 && month == 1) { return; } //extra: if (date_clicked) month--; if (month < 1) { month = 12; year--; } dateChanged(year, month, day); dayChanged(this->date,clickDate); } //显示下月日期 void LunarCalendarWidget::showNextMonth(bool date_clicked) { int year = date.year(); int month = date.month(); int day = date.day(); if (year >= 2099 ) { return; } //extra if (date_clicked)month++; if (month > 12) { month = 1; year++; } dateChanged(year, month, day); dayChanged(this->date,clickDate); } //转到今天 void LunarCalendarWidget::showToday() { widgetYearBody->hide(); widgetmonthBody->hide(); widgetDayBody->show(); widgetWeek->show(); date = QDate::currentDate(); initDate(); dayChanged(this->date,clickDate); } void LunarCalendarWidget::setCalendarStyle(const LunarCalendarWidget::CalendarStyle &calendarStyle) { if (this->calendarStyle != calendarStyle) { this->calendarStyle = calendarStyle; } } void LunarCalendarWidget::setWeekNameFormat(bool FirstDayisSun) { FirstdayisSun = FirstDayisSun; if (FirstdayisSun) { // listWeek << "日" << "一" << "二" << "三" << "四" << "五" << "六"; // listWeek << "周日" << "周一" << "周二" << "周三" << "周四" << "周五" << "周六"; // listWeek << "星期天" << "星期一" << "星期二" << "星期三" << "星期四" << "星期五" << "星期六"; // listWeek << "Sun" << "Mon" << "Tue" << "Wed" << "Thur" << "Fri" << "Sat"; QTimer::singleShot(0,this,[=]{ labWeeks.at(0)->setText((tr("Sunday"))); labWeeks.at(1)->setText((tr("Monday"))); labWeeks.at(2)->setText((tr("Tuesday"))); labWeeks.at(3)->setText((tr("Wednesday"))); labWeeks.at(4)->setText((tr("Thursday"))); labWeeks.at(5)->setText((tr("Friday"))); labWeeks.at(6)->setText((tr("Saturday"))); }); } else { QTimer::singleShot(0,this,[=]{ labWeeks.at(0)->setText((tr("Monday"))); labWeeks.at(1)->setText((tr("Tuesday"))); labWeeks.at(2)->setText((tr("Wednesday"))); labWeeks.at(3)->setText((tr("Thursday"))); labWeeks.at(4)->setText((tr("Friday"))); labWeeks.at(5)->setText((tr("Saturday"))); labWeeks.at(6)->setText((tr("Sunday"))); }); } initDate(); } void LunarCalendarWidget::setDate(const QDate &date) { if (this->date != date) { this->date = date; initDate(); } } void LunarCalendarWidget::setWeekTextColor(const QColor &weekTextColor) { if (this->weekTextColor != weekTextColor) { this->weekTextColor = weekTextColor; initStyle(); } } void LunarCalendarWidget::setWeekBgColor(const QColor &weekBgColor) { if (this->weekBgColor != weekBgColor) { this->weekBgColor = weekBgColor; initStyle(); } } void LunarCalendarWidget::setShowLunar(bool showLunar) { this->showLunar = showLunar; initStyle(); } void LunarCalendarWidget::setBgImage(const QString &bgImage) { if (this->bgImage != bgImage) { this->bgImage = bgImage; initStyle(); } } void LunarCalendarWidget::setSelectType(const LunarCalendarWidget::SelectType &selectType) { if (this->selectType != selectType) { this->selectType = selectType; initStyle(); } } void LunarCalendarWidget::setBorderColor(const QColor &borderColor) { if (this->borderColor != borderColor) { this->borderColor = borderColor; initStyle(); } } void LunarCalendarWidget::setWeekColor(const QColor &weekColor) { if (this->weekColor != weekColor) { this->weekColor = weekColor; initStyle(); } } void LunarCalendarWidget::setSuperColor(const QColor &superColor) { if (this->superColor != superColor) { this->superColor = superColor; initStyle(); } } void LunarCalendarWidget::setLunarColor(const QColor &lunarColor) { if (this->lunarColor != lunarColor) { this->lunarColor = lunarColor; initStyle(); } } void LunarCalendarWidget::setCurrentTextColor(const QColor ¤tTextColor) { if (this->currentTextColor != currentTextColor) { this->currentTextColor = currentTextColor; initStyle(); } } void LunarCalendarWidget::setOtherTextColor(const QColor &otherTextColor) { if (this->otherTextColor != otherTextColor) { this->otherTextColor = otherTextColor; initStyle(); } } void LunarCalendarWidget::setSelectTextColor(const QColor &selectTextColor) { if (this->selectTextColor != selectTextColor) { this->selectTextColor = selectTextColor; initStyle(); } } void LunarCalendarWidget::setHoverTextColor(const QColor &hoverTextColor) { if (this->hoverTextColor != hoverTextColor) { this->hoverTextColor = hoverTextColor; initStyle(); } } void LunarCalendarWidget::setCurrentLunarColor(const QColor ¤tLunarColor) { if (this->currentLunarColor != currentLunarColor) { this->currentLunarColor = currentLunarColor; initStyle(); } } void LunarCalendarWidget::setOtherLunarColor(const QColor &otherLunarColor) { if (this->otherLunarColor != otherLunarColor) { this->otherLunarColor = otherLunarColor; initStyle(); } } void LunarCalendarWidget::setSelectLunarColor(const QColor &selectLunarColor) { if (this->selectLunarColor != selectLunarColor) { this->selectLunarColor = selectLunarColor; initStyle(); } } void LunarCalendarWidget::setHoverLunarColor(const QColor &hoverLunarColor) { if (this->hoverLunarColor != hoverLunarColor) { this->hoverLunarColor = hoverLunarColor; initStyle(); } } void LunarCalendarWidget::setCurrentBgColor(const QColor ¤tBgColor) { if (this->currentBgColor != currentBgColor) { this->currentBgColor = currentBgColor; initStyle(); } } void LunarCalendarWidget::setOtherBgColor(const QColor &otherBgColor) { if (this->otherBgColor != otherBgColor) { this->otherBgColor = otherBgColor; initStyle(); } } void LunarCalendarWidget::setSelectBgColor(const QColor &selectBgColor) { if (this->selectBgColor != selectBgColor) { this->selectBgColor = selectBgColor; initStyle(); } } void LunarCalendarWidget::setHoverBgColor(const QColor &hoverBgColor) { if (this->hoverBgColor != hoverBgColor) { this->hoverBgColor = hoverBgColor; initStyle(); } } void LunarCalendarWidget::wheelEvent(QWheelEvent *event) { if (event->delta() > 0) showPreviousMonth(); else showNextMonth(); } m_PartLineWidget::m_PartLineWidget(QWidget *parent) : QWidget(parent) { } void m_PartLineWidget::paintEvent(QPaintEvent *event) { QPainter p(this); QRect rect = this->rect(); p.setRenderHint(QPainter::Antialiasing); // 反锯齿; QColor color=qApp->palette().color(QPalette::Base); if(color.red() == 255 && color.green() == 255 && color.blue() == 255){ color.setRgb(1,1,1,255); } else if (color.red() == 31 && color.green() == 32 && color.blue() == 34) { color.setRgb(255,255,255,255); } p.setBrush(color); p.setOpacity(0.05); p.setPen(Qt::NoPen); p.drawRoundedRect(rect,0,0); QWidget::paintEvent(event); } statelabel::statelabel() : QLabel() { } //鼠标点击事件 void statelabel::mousePressEvent(QMouseEvent *event) { if (event->buttons() == Qt::LeftButton){ Q_EMIT labelclick(); } return; } ukui-panel-3.0.6.4/ukui-calendar/lunarcalendarwidget/lunarcalendaritem.cpp0000644000175000017500000004521114203402514025313 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see LunarCalendarItem::LunarCalendarItem(QWidget *parent) : QWidget(parent) { hover = false; pressed = false; select = false; showLunar = true; bgImage = ":/image/bg_calendar.png"; selectType = SelectType_Rect; date = QDate::currentDate(); lunar = "初一"; dayType = DayType_MonthCurrent; //实时监听主题变化 const QByteArray id("org.ukui.style"); QGSettings * fontSetting = new QGSettings(id, QByteArray(), this); connect(fontSetting, &QGSettings::changed,[=](QString key) { if(fontSetting->get("style-name").toString() == "ukui-default") { weekColor = QColor(255, 255, 255); currentTextColor = QColor(255, 255, 255); otherTextColor = QColor(255, 255, 255,40); otherLunarColor = QColor(255, 255, 255,40); currentLunarColor = QColor(255, 255, 255,90); lunarColor = QColor(255, 255, 255,90); } else if(fontSetting->get("style-name").toString() == "ukui-light") { weekColor = QColor(0, 0, 0); currentTextColor = QColor(0, 0, 0); otherTextColor = QColor(0,0,0,40); otherLunarColor = QColor(0,0,0,40); currentLunarColor = QColor(0,0,0,90); lunarColor = QColor(0,0,0,90); } else if(fontSetting->get("style-name").toString() == "ukui-dark") { weekColor = QColor(255, 255, 255); currentTextColor = QColor(255, 255, 255); otherTextColor = QColor(255, 255, 255,40); otherLunarColor = QColor(255, 255, 255,40); currentLunarColor = QColor(255, 255, 255,90); lunarColor = QColor(255, 255, 255,90); } }); if(fontSetting->get("style-name").toString() == "ukui-light") { weekColor = QColor(0, 0, 0); currentTextColor = QColor(0, 0, 0); otherTextColor = QColor(0,0,0,40); otherLunarColor = QColor(0,0,0,40); currentLunarColor = QColor(0,0,0,90); lunarColor = QColor(0,0,0,90); } else { weekColor = QColor(255, 255, 255); currentTextColor = QColor(255, 255, 255); otherTextColor = QColor(255, 255, 255,40); otherLunarColor = QColor(255, 255, 255,40); currentLunarColor = QColor(255, 255, 255,90); lunarColor = QColor(255, 255, 255,90); } borderColor = QColor(180, 180, 180); superColor = QColor(255, 129, 6); selectTextColor = QColor(255, 255, 255); hoverTextColor = QColor(250, 250, 250); selectLunarColor = QColor(255, 255, 255); hoverLunarColor = QColor(250, 250, 250); currentBgColor = QColor(255, 255, 255); otherBgColor = QColor(240, 240, 240); selectBgColor = QColor(55,143,250); hoverBgColor = QColor(204, 183, 180); } void LunarCalendarItem::enterEvent(QEvent *) { hover = true; this->update(); } void LunarCalendarItem::leaveEvent(QEvent *) { hover = false; this->update(); } void LunarCalendarItem::mousePressEvent(QMouseEvent *) { pressed = true; this->update(); Q_EMIT clicked(date, dayType); } void LunarCalendarItem::mouseReleaseEvent(QMouseEvent *) { pressed = false; this->update(); } QString LunarCalendarItem::handleJsMap(QString year,QString month2day) { QString oneNUmber = "worktime.y" + year; QString twoNumber = "d" + month2day; QMap>::Iterator it = worktime.begin(); while(it!=worktime.end()) { if(it.key() == oneNUmber) { QMap::Iterator it1 = it.value().begin(); while(it1!=it.value().end()) { if(it1.key() == twoNumber) { return it1.value(); } it1++; } } it++; } return "-1"; } void LunarCalendarItem::paintEvent(QPaintEvent *) { QDate dateNow = QDate::currentDate(); //绘制准备工作,启用反锯齿 QPainter painter(this); painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing); //绘制背景和边框 drawBg(&painter); //对比当前的时间,画选中状态 if(dateNow == date) { drawBgCurrent(&painter, selectBgColor); } //绘制悬停状态 if (hover) { drawBgHover(&painter, hoverBgColor); } //绘制选中状态 if (select) { drawBgHover(&painter, hoverBgColor); } //绘制日期 drawDay(&painter); //绘制农历信息 drawLunar(&painter); } void LunarCalendarItem::drawBg(QPainter *painter) { painter->save(); //根据当前类型选择对应的颜色 QColor bgColor = currentBgColor; if (dayType == DayType_MonthPre || dayType == DayType_MonthNext) { bgColor = otherBgColor; } //painter->setPen(borderColor); //painter->setBrush(bgColor); //painter->drawRect(rect()); painter->restore(); } void LunarCalendarItem::drawBgCurrent(QPainter *painter, const QColor &color) { painter->save(); painter->setPen(Qt::NoPen); painter->setBrush(color); QRect rect = this->rect(); painter->drawRoundedRect(rect,4,4); // //根据设定绘制背景样式 // if (selectType == SelectType_Rect) { // } painter->restore(); } void LunarCalendarItem::drawBgHover(QPainter *painter, const QColor &color) { painter->save(); QRect rect = this->rect(); painter->setPen(QPen(QColor(55,143,250),2)); painter->drawRoundedRect(rect,4,4); // //根据设定绘制背景样式 // if (selectType == SelectType_Rect) { // } painter->restore(); } void LunarCalendarItem::drawDay(QPainter *painter) { int width = this->width(); int height = this->height(); int side = qMin(width, height); painter->save(); //根据当前类型选择对应的颜色 QColor color = currentTextColor; if (dayType == DayType_MonthPre || dayType == DayType_MonthNext) { color = otherTextColor; } else if (dayType == DayType_WeekEnd) { color = weekColor; } /* if (select) { color = selectTextColor; } *//*else if (hover) { color = hoverTextColor; }*/ painter->setPen(color); QFont font; font.setPixelSize(side * 0.3); //设置文字粗细 font.setBold(true); painter->setFont(font); //代码复用率待优化 if (showLunar) { QRect dayRect = QRect(0, 0, width, height / 1.7); painter->drawText(dayRect, Qt::AlignHCenter | Qt::AlignBottom, QString::number(date.day())); if (handleJsMap(date.toString("yyyy"),date.toString("MMdd")) == "2") { painter->setPen(Qt::NoPen); painter->setBrush(QColor(244,78,80)); QRect dayRect1 = QRect(0, 0, width/3.5,height/3.5); painter->drawRoundedRect(dayRect1,1,1); font.setPixelSize(side / 5); painter->setFont(font); painter->setPen(Qt::white); painter->drawText(dayRect1, Qt::AlignHCenter | Qt::AlignBottom,"休"); } else if (handleJsMap(date.toString("yyyy"),date.toString("MMdd")) == "1") { painter->setPen(Qt::NoPen); painter->setBrush(QColor(251,170,42)); QRect dayRect1 = QRect(0, 0, width/3.5,height/3.5); painter->drawRoundedRect(dayRect1,1,1); font.setPixelSize(side / 5); painter->setFont(font); painter->setPen(Qt::white); painter->drawText(dayRect1, Qt::AlignHCenter | Qt::AlignBottom,"班"); } } else { QRect dayRect = QRect(0, 0, width, height); painter->drawText(dayRect, Qt::AlignCenter, QString::number(date.day())); if (handleJsMap(date.toString("yyyy"),date.toString("MMdd")) == "2") { painter->setPen(Qt::NoPen); painter->setBrush(QColor(255,0,0)); QRect dayRect1 = QRect(0, 0, width/3.5,height/3.5); painter->drawRoundedRect(dayRect1,1,1); font.setPixelSize(side / 5); painter->setFont(font); painter->setPen(Qt::white); painter->drawText(dayRect1, Qt::AlignHCenter | Qt::AlignBottom,"休"); } else if (handleJsMap(date.toString("yyyy"),date.toString("MMdd")) == "1") { painter->setPen(Qt::NoPen); painter->setBrush(QColor(251,170,42)); QRect dayRect1 = QRect(0, 0, width/3.5,height/3.5); painter->drawRoundedRect(dayRect1,1,1); font.setPixelSize(side / 5); painter->setFont(font); painter->setPen(Qt::white); painter->drawText(dayRect1, Qt::AlignHCenter | Qt::AlignBottom,"班"); } } painter->restore(); } void LunarCalendarItem::drawLunar(QPainter *painter) { if (!showLunar) { return; } int width = this->width(); int height = this->height(); int side = qMin(width, height); painter->save(); QStringList listDayName; listDayName << "*" << "初一" << "初二" << "初三" << "初四" << "初五" << "初六" << "初七" << "初八" << "初九" << "初十" << "十一" << "十二" << "十三" << "十四" << "十五" << "十六" << "十七" << "十八" << "十九" << "二十" << "廿一" << "廿二" << "廿三" << "廿四" << "廿五" << "廿六" << "廿七" << "廿八" << "廿九" << "三十"; //判断当前农历文字是否节日,是节日且是当月则用农历节日颜色显示 bool exist = (!listDayName.contains(lunar) && dayType != DayType_MonthPre && dayType != DayType_MonthNext); //根据当前类型选择对应的颜色 QColor color = currentLunarColor; if (dayType == DayType_MonthPre || dayType == DayType_MonthNext) { color = otherLunarColor; } // if (select) { // color = selectTextColor; // } /*else if (hover) { // color = hoverTextColor; // }*/ else if (exist) { // color = lunarColor; // } if (exist) { color = lunarColor; } painter->setPen(color); QFont font; font.setPixelSize(side * 0.27); painter->setFont(font); QRect lunarRect(0, height / 2, width, height / 2); painter->drawText(lunarRect, Qt::AlignCenter, lunar); painter->restore(); } bool LunarCalendarItem::getSelect() const { return this->select; } bool LunarCalendarItem::getShowLunar() const { return this->showLunar; } QString LunarCalendarItem::getBgImage() const { return this->bgImage; } LunarCalendarItem::SelectType LunarCalendarItem::getSelectType() const { return this->selectType; } QDate LunarCalendarItem::getDate() const { return this->date; } QString LunarCalendarItem::getLunar() const { return this->lunar; } LunarCalendarItem::DayType LunarCalendarItem::getDayType() const { return this->dayType; } QColor LunarCalendarItem::getBorderColor() const { return this->borderColor; } QColor LunarCalendarItem::getWeekColor() const { return this->weekColor; } QColor LunarCalendarItem::getSuperColor() const { return this->superColor; } QColor LunarCalendarItem::getLunarColor() const { return this->lunarColor; } QColor LunarCalendarItem::getCurrentTextColor() const { return this->currentTextColor; } QColor LunarCalendarItem::getOtherTextColor() const { return this->otherTextColor; } QColor LunarCalendarItem::getSelectTextColor() const { return this->selectTextColor; } QColor LunarCalendarItem::getHoverTextColor() const { return this->hoverTextColor; } QColor LunarCalendarItem::getCurrentLunarColor() const { return this->currentLunarColor; } QColor LunarCalendarItem::getOtherLunarColor() const { return this->otherLunarColor; } QColor LunarCalendarItem::getSelectLunarColor() const { return this->selectLunarColor; } QColor LunarCalendarItem::getHoverLunarColor() const { return this->hoverLunarColor; } QColor LunarCalendarItem::getCurrentBgColor() const { return this->currentBgColor; } QColor LunarCalendarItem::getOtherBgColor() const { return this->otherBgColor; } QColor LunarCalendarItem::getSelectBgColor() const { return this->selectBgColor; } QColor LunarCalendarItem::getHoverBgColor() const { return this->hoverBgColor; } QSize LunarCalendarItem::sizeHint() const { return QSize(100, 100); } QSize LunarCalendarItem::minimumSizeHint() const { return QSize(20, 20); } void LunarCalendarItem::setSelect(bool select) { if (this->select != select) { this->select = select; this->update(); } } void LunarCalendarItem::setShowLunar(bool showLunar) { this->showLunar = showLunar; this->update(); } void LunarCalendarItem::setBgImage(const QString &bgImage) { if (this->bgImage != bgImage) { this->bgImage = bgImage; this->update(); } } void LunarCalendarItem::setSelectType(const LunarCalendarItem::SelectType &selectType) { if (this->selectType != selectType) { this->selectType = selectType; this->update(); } } void LunarCalendarItem::setDate(const QDate &date) { if (this->date != date) { this->date = date; this->update(); } } void LunarCalendarItem::setLunar(const QString &lunar) { if (this->lunar != lunar) { this->lunar = lunar; this->update(); } } void LunarCalendarItem::setDayType(const LunarCalendarItem::DayType &dayType) { if (this->dayType != dayType) { this->dayType = dayType; this->update(); } } void LunarCalendarItem::setDate(const QDate &date, const QString &lunar, const DayType &dayType) { this->date = date; this->lunar = lunar; this->dayType = dayType; this->update(); } void LunarCalendarItem::setBorderColor(const QColor &borderColor) { if (this->borderColor != borderColor) { this->borderColor = borderColor; this->update(); } } void LunarCalendarItem::setWeekColor(const QColor &weekColor) { if (this->weekColor != weekColor) { this->weekColor = weekColor; this->update(); } } void LunarCalendarItem::setSuperColor(const QColor &superColor) { if (this->superColor != superColor) { this->superColor = superColor; this->update(); } } void LunarCalendarItem::setLunarColor(const QColor &lunarColor) { if (this->lunarColor != lunarColor) { this->lunarColor = lunarColor; this->update(); } } void LunarCalendarItem::setCurrentTextColor(const QColor ¤tTextColor) { if (this->currentTextColor != currentTextColor) { this->currentTextColor = currentTextColor; this->update(); } } void LunarCalendarItem::setOtherTextColor(const QColor &otherTextColor) { if (this->otherTextColor != otherTextColor) { this->otherTextColor = otherTextColor; this->update(); } } void LunarCalendarItem::setSelectTextColor(const QColor &selectTextColor) { if (this->selectTextColor != selectTextColor) { this->selectTextColor = selectTextColor; this->update(); } } void LunarCalendarItem::setHoverTextColor(const QColor &hoverTextColor) { if (this->hoverTextColor != hoverTextColor) { this->hoverTextColor = hoverTextColor; this->update(); } } void LunarCalendarItem::setCurrentLunarColor(const QColor ¤tLunarColor) { if (this->currentLunarColor != currentLunarColor) { this->currentLunarColor = currentLunarColor; this->update(); } } void LunarCalendarItem::setOtherLunarColor(const QColor &otherLunarColor) { if (this->otherLunarColor != otherLunarColor) { this->otherLunarColor = otherLunarColor; this->update(); } } void LunarCalendarItem::setSelectLunarColor(const QColor &selectLunarColor) { if (this->selectLunarColor != selectLunarColor) { this->selectLunarColor = selectLunarColor; this->update(); } } void LunarCalendarItem::setHoverLunarColor(const QColor &hoverLunarColor) { if (this->hoverLunarColor != hoverLunarColor) { this->hoverLunarColor = hoverLunarColor; this->update(); } } void LunarCalendarItem::setCurrentBgColor(const QColor ¤tBgColor) { if (this->currentBgColor != currentBgColor) { this->currentBgColor = currentBgColor; this->update(); } } void LunarCalendarItem::setOtherBgColor(const QColor &otherBgColor) { if (this->otherBgColor != otherBgColor) { this->otherBgColor = otherBgColor; this->update(); } } void LunarCalendarItem::setSelectBgColor(const QColor &selectBgColor) { if (this->selectBgColor != selectBgColor) { this->selectBgColor = selectBgColor; this->update(); } } void LunarCalendarItem::setHoverBgColor(const QColor &hoverBgColor) { if (this->hoverBgColor != hoverBgColor) { this->hoverBgColor = hoverBgColor; this->update(); } } bool LunarCalendarItem::event(QEvent *event) { if(event->type()==QEvent::ToolTip){ if(date.month()==11 && date.day()==9 ){ setToolTip(tr("消防宣传日")); } if(date.month()==3 && date.day()==5 ){ setToolTip(tr("志愿者服务日")); } if(date.month()==6 && date.day()==6 ){ setToolTip(tr("全国爱眼日")); } if(date.month()==7 && date.day()==7 ){ setToolTip(tr("抗战纪念日")); } } return QWidget::event(event); } ukui-panel-3.0.6.4/ukui-calendar/lunarcalendarwidget/frmlunarcalendarwidget.cpp0000644000175000017500000002155514203402514026352 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #define TRANSPARENCY_SETTINGS "org.ukui.control-center.personalise" #define TRANSPARENCY_KEY "transparency" #define PANEL_CONTROL_IN_CALENDAR "org.ukui.control-center.panel.plugins" #define LUNAR_KEY "calendar" #define FIRST_DAY_KEY "firstday" frmLunarCalendarWidget::frmLunarCalendarWidget(QWidget *parent) : QWidget(parent), ui(new Ui::frmLunarCalendarWidget), mCalendarDBus(new CalendarDBus(this)) { installEventFilter(this); ui->setupUi(this); this->hide(); connect(ui->lunarCalendarWidget,&LunarCalendarWidget::yijiChangeUp,this,&frmLunarCalendarWidget::changeUpSize); connect(ui->lunarCalendarWidget,&LunarCalendarWidget::yijiChangeDown,this,&frmLunarCalendarWidget::changeDownSize); connect(ui->lunarCalendarWidget,&LunarCalendarWidget::yijiChangeUp,this,&frmLunarCalendarWidget::set_window_position); connect(ui->lunarCalendarWidget,&LunarCalendarWidget::yijiChangeDown,this,&frmLunarCalendarWidget::set_window_position); connect(mCalendarDBus,&CalendarDBus::ShowCalendarWidget,this,[=](){ KWindowSystem::setState(this->winId(),NET::SkipTaskbar | NET::SkipPager); if (this->isHidden()){ this->show(); this->activateWindow(); }else { this->hide(); } }); this->initForm(); // this->setWindowFlags(Qt::X11BypassWindowManagerHint); // this->setWindowFlags(Qt::FramelessWindowHint | Qt::Popup); KWindowSystem::setState(this->winId(),NET::SkipTaskbar | NET::SkipPager); // setAttribute(Qt::WA_TranslucentBackground);//设置窗口背景透明 setProperty("useSystemStyleBlur", true); this->setFixedSize(440, 600); set_window_position(); const QByteArray transparency_id(TRANSPARENCY_SETTINGS); if(QGSettings::isSchemaInstalled(transparency_id)){ transparency_gsettings = new QGSettings(transparency_id); } const QByteArray calendar_id(PANEL_CONTROL_IN_CALENDAR); if(QGSettings::isSchemaInstalled(calendar_id)){ calendar_gsettings = new QGSettings(calendar_id); //公历/农历切换 connect(calendar_gsettings, &QGSettings::changed, this, [=] (const QString &key){ if(key == LUNAR_KEY){ ckShowLunar_stateChanged(calendar_gsettings->get(LUNAR_KEY).toString() == "lunar"); } if (key == FIRST_DAY_KEY) { cboxWeekNameFormat_currentIndexChanged(calendar_gsettings->get(FIRST_DAY_KEY).toString() == "sunday"); } }); } else { ckShowLunar_stateChanged(false); cboxWeekNameFormat_currentIndexChanged(false); } } frmLunarCalendarWidget::~frmLunarCalendarWidget() { delete ui; } void frmLunarCalendarWidget::changeUpSize() { this->setFixedSize(440, 652); Q_EMIT yijiChangeUp(); } void frmLunarCalendarWidget::changeDownSize() { this->setFixedSize(440, 600); Q_EMIT yijiChangeDown(); } void frmLunarCalendarWidget::initForm() { //ui->cboxWeekNameFormat->setCurrentIndex(0); } void frmLunarCalendarWidget::cboxCalendarStyle_currentIndexChanged(int index) { ui->lunarCalendarWidget->setCalendarStyle((LunarCalendarWidget::CalendarStyle)index); } void frmLunarCalendarWidget::cboxSelectType_currentIndexChanged(int index) { ui->lunarCalendarWidget->setSelectType((LunarCalendarWidget::SelectType)index); } void frmLunarCalendarWidget::cboxWeekNameFormat_currentIndexChanged(bool FirstDayisSun) { ui->lunarCalendarWidget->setWeekNameFormat(FirstDayisSun); } void frmLunarCalendarWidget::ckShowLunar_stateChanged(bool arg1) { ui->lunarCalendarWidget->setShowLunar(arg1); } void frmLunarCalendarWidget::paintEvent(QPaintEvent *) { QStyleOption opt; opt.init(this); QRect rect = this->rect(); QPainter p(this); double tran =1; const QByteArray transparency_id(TRANSPARENCY_SETTINGS); if(QGSettings::isSchemaInstalled(transparency_id)){ tran=transparency_gsettings->get(TRANSPARENCY_KEY).toDouble()*255; } QColor color = palette().color(QPalette::Base); color.setAlpha(tran); QBrush brush =QBrush(color); p.setBrush(brush); p.setPen(Qt::NoPen); p.setRenderHint(QPainter::Antialiasing); p.drawRoundedRect(rect,6,6); style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); } /* * 事件过滤,检测鼠标点击外部活动区域则收回收纳栏 */ bool frmLunarCalendarWidget::eventFilter(QObject *obj, QEvent *event) { if (event->type() == QEvent::Leave) { qDebug()<<"event->type() == QEvent::ActivationChange"; if(QApplication::activeWindow() != this) { qDebug()<<"this->hide()"; this->hide(); } } return QWidget::event(event); if (obj == this) { qDebug()<<"obj == this"; if (event->type() == QEvent::MouseButtonPress) { qDebug()<<"QEvent::MouseButtonPress"; QMouseEvent *mouseEvent = static_cast(event); if (mouseEvent->button() == Qt::LeftButton) { qDebug()<<"激活内部窗口"; this->hide(); return true; } else if(mouseEvent->button() == Qt::RightButton) { return true; } } else if(event->type() == QEvent::ContextMenu) { return false; } else if (event->type() == QEvent::WindowDeactivate) { qDebug()<<"激活外部窗口"; this->hide(); return true; } else if (event->type() == QEvent::StyleChange) { } } if (!isActiveWindow()) { activateWindow(); } // return false; } void frmLunarCalendarWidget::set_window_position(){ QDBusInterface iface("org.ukui.panel", "/panel/position", "org.ukui.panel", QDBusConnection::sessionBus()); QDBusReply < QVariantList > reply =iface.call("GetPrimaryScreenGeometry"); // qDebug() << reply.value().at(2).toInt(); // qDebug() << reply.value().at(3).toInt(); // qDebug() <width(); // qDebug() <height(); switch (reply.value().at(4).toInt()) { case 1: this->setGeometry(reply.value().at(0).toInt() + reply.value().at(2).toInt() - this->width() - 4, reply.value().at(1).toInt() + 4, this->width(), this->height()); break; case 2: this->setGeometry(reply.value().at(0).toInt() + 4, reply.value().at(3).toInt()- this->height() - 4, this->width(), this->height()); break; case 3: this->setGeometry(reply.value().at(2).toInt() - this->width() - 4, reply.value().at(3).toInt()-this->height()- 4, this->width(), this->height()); break; default: this->setGeometry(reply.value().at(0).toInt() + reply.value().at(2).toInt() - this->width() - 4, reply.value().at(1).toInt() + reply.value().at(3).toInt() - this->height() - 4, this->width(), this->height()); break; } } void frmLunarCalendarWidget::mousePressEvent(QMouseEvent *event){ if (Qt::LeftButton == event->button() ){ qDebug()<<"leftbutton pressed!!!"; if(QApplication::activeWindow() != this) { qDebug()<<"this->hide()"; qDebug()<hide(); } if(this->isHidden()){ this->show(); }else { this->hide(); } } } ukui-panel-3.0.6.4/ukui-calendar/lunarcalendarwidget/lunarcalendaryearitem.cpp0000644000175000017500000003047114203402514026176 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see LunarCalendarYearItem::LunarCalendarYearItem(QWidget *parent) : QWidget(parent) { hover = false; pressed = false; select = false; showLunar = true; bgImage = ":/image/bg_calendar.png"; selectType = SelectType_Rect; date = QDate::currentDate(); lunar = "初一"; dayType = DayType_MonthCurrent; //实时监听主题变化 const QByteArray id("org.ukui.style"); QGSettings * fontSetting = new QGSettings(id, QByteArray(), this); connect(fontSetting, &QGSettings::changed,[=](QString key) { if(fontSetting->get("style-name").toString() == "ukui-default") { weekColor = QColor(255, 255, 255); currentTextColor = QColor(255, 255, 255); otherTextColor = QColor(255, 255, 255,40); otherLunarColor = QColor(255, 255, 255,40); currentLunarColor = QColor(255, 255, 255,90); lunarColor = QColor(255, 255, 255,90); } else if(fontSetting->get("style-name").toString() == "ukui-light") { weekColor = QColor(0, 0, 0); currentTextColor = QColor(0, 0, 0); otherTextColor = QColor(0,0,0,40); otherLunarColor = QColor(0,0,0,40); currentLunarColor = QColor(0,0,0,90); lunarColor = QColor(0,0,0,90); } else if(fontSetting->get("style-name").toString() == "ukui-dark") { weekColor = QColor(255, 255, 255); currentTextColor = QColor(255, 255, 255); otherTextColor = QColor(255, 255, 255,40); otherLunarColor = QColor(255, 255, 255,40); currentLunarColor = QColor(255, 255, 255,90); lunarColor = QColor(255, 255, 255,90); } }); if(fontSetting->get("style-name").toString() == "ukui-light") { weekColor = QColor(0, 0, 0); currentTextColor = QColor(0, 0, 0); otherTextColor = QColor(0,0,0,40); otherLunarColor = QColor(0,0,0,40); currentLunarColor = QColor(0,0,0,90); lunarColor = QColor(0,0,0,90); } else { weekColor = QColor(255, 255, 255); currentTextColor = QColor(255, 255, 255); otherTextColor = QColor(255, 255, 255,40); otherLunarColor = QColor(255, 255, 255,40); currentLunarColor = QColor(255, 255, 255,90); lunarColor = QColor(255, 255, 255,90); } borderColor = QColor(180, 180, 180); superColor = QColor(255, 129, 6); selectTextColor = QColor(255, 255, 255); hoverTextColor = QColor(250, 250, 250); selectLunarColor = QColor(255, 255, 255); hoverLunarColor = QColor(250, 250, 250); currentBgColor = QColor(255, 255, 255); otherBgColor = QColor(240, 240, 240); selectBgColor = QColor(55,143,250); hoverBgColor = QColor(204, 183, 180); } void LunarCalendarYearItem::enterEvent(QEvent *) { hover = true; this->update(); } void LunarCalendarYearItem::leaveEvent(QEvent *) { hover = false; this->update(); } void LunarCalendarYearItem::mousePressEvent(QMouseEvent *) { pressed = true; this->update(); // Q_EMIT clicked(date, dayType); Q_EMIT yearMessage(date, dayType); } void LunarCalendarYearItem::mouseReleaseEvent(QMouseEvent *) { pressed = false; this->update(); } void LunarCalendarYearItem::paintEvent(QPaintEvent *) { QDate dateNow = QDate::currentDate(); //绘制准备工作,启用反锯齿 QPainter painter(this); painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing); //绘制背景和边框 drawBg(&painter); //对比当前的时间,画选中状态 if(dateNow.year() == date.year()) { drawBgCurrent(&painter, selectBgColor); } //绘制悬停状态 if (hover) { drawBgHover(&painter, hoverBgColor); } //绘制选中状态 if (select) { drawBgHover(&painter, hoverBgColor); } //绘制日期 drawYear(&painter); } void LunarCalendarYearItem::drawBg(QPainter *painter) { painter->save(); //根据当前类型选择对应的颜色 QColor bgColor = currentBgColor; if (dayType == DayType_MonthPre || dayType == DayType_MonthNext) { bgColor = otherBgColor; } painter->restore(); } void LunarCalendarYearItem::drawBgCurrent(QPainter *painter, const QColor &color) { painter->save(); painter->setPen(Qt::NoPen); painter->setBrush(color); QRect rect = this->rect(); painter->drawRoundedRect(rect,4,4); painter->restore(); } void LunarCalendarYearItem::drawBgHover(QPainter *painter, const QColor &color) { painter->save(); QRect rect = this->rect(); painter->setPen(QPen(QColor(55,143,250),2)); painter->drawRoundedRect(rect,4,4); painter->restore(); } void LunarCalendarYearItem::drawYear(QPainter *painter) { int width = this->width(); int height = this->height(); int side = qMin(width, height); painter->save(); //根据当前类型选择对应的颜色 QColor color = currentTextColor; if (dayType == DayType_MonthPre || dayType == DayType_MonthNext) { color = otherTextColor; } else if (dayType == DayType_WeekEnd) { color = weekColor; } painter->setPen(color); QFont font; font.setPixelSize(side * 0.2); //设置文字粗细 font.setBold(true); painter->setFont(font); QRect dayRect = QRect(0, 0, width, height / 1.7); QString arg = QString::number(date.year()) + "年"; painter->drawText(dayRect, Qt::AlignHCenter | Qt::AlignBottom, arg); painter->restore(); } bool LunarCalendarYearItem::getSelect() const { return this->select; } bool LunarCalendarYearItem::getShowLunar() const { return this->showLunar; } QString LunarCalendarYearItem::getBgImage() const { return this->bgImage; } LunarCalendarYearItem::SelectType LunarCalendarYearItem::getSelectType() const { return this->selectType; } QDate LunarCalendarYearItem::getDate() const { return this->date; } QString LunarCalendarYearItem::getLunar() const { return this->lunar; } LunarCalendarYearItem::DayType LunarCalendarYearItem::getDayType() const { return this->dayType; } QColor LunarCalendarYearItem::getBorderColor() const { return this->borderColor; } QColor LunarCalendarYearItem::getWeekColor() const { return this->weekColor; } QColor LunarCalendarYearItem::getSuperColor() const { return this->superColor; } QColor LunarCalendarYearItem::getLunarColor() const { return this->lunarColor; } QColor LunarCalendarYearItem::getCurrentTextColor() const { return this->currentTextColor; } QColor LunarCalendarYearItem::getOtherTextColor() const { return this->otherTextColor; } QColor LunarCalendarYearItem::getSelectTextColor() const { return this->selectTextColor; } QColor LunarCalendarYearItem::getHoverTextColor() const { return this->hoverTextColor; } QColor LunarCalendarYearItem::getCurrentLunarColor() const { return this->currentLunarColor; } QColor LunarCalendarYearItem::getOtherLunarColor() const { return this->otherLunarColor; } QColor LunarCalendarYearItem::getSelectLunarColor() const { return this->selectLunarColor; } QColor LunarCalendarYearItem::getHoverLunarColor() const { return this->hoverLunarColor; } QColor LunarCalendarYearItem::getCurrentBgColor() const { return this->currentBgColor; } QColor LunarCalendarYearItem::getOtherBgColor() const { return this->otherBgColor; } QColor LunarCalendarYearItem::getSelectBgColor() const { return this->selectBgColor; } QColor LunarCalendarYearItem::getHoverBgColor() const { return this->hoverBgColor; } QSize LunarCalendarYearItem::sizeHint() const { return QSize(100, 100); } QSize LunarCalendarYearItem::minimumSizeHint() const { return QSize(20, 20); } void LunarCalendarYearItem::setSelect(bool select) { if (this->select != select) { this->select = select; this->update(); } } void LunarCalendarYearItem::setShowLunar(bool showLunar) { this->showLunar = showLunar; this->update(); } void LunarCalendarYearItem::setBgImage(const QString &bgImage) { if (this->bgImage != bgImage) { this->bgImage = bgImage; this->update(); } } void LunarCalendarYearItem::setSelectType(const LunarCalendarYearItem::SelectType &selectType) { if (this->selectType != selectType) { this->selectType = selectType; this->update(); } } void LunarCalendarYearItem::setDate(const QDate &date) { if (this->date != date) { this->date = date; this->update(); } } void LunarCalendarYearItem::setLunar(const QString &lunar) { if (this->lunar != lunar) { this->lunar = lunar; this->update(); } } void LunarCalendarYearItem::setDayType(const LunarCalendarYearItem::DayType &dayType) { if (this->dayType != dayType) { this->dayType = dayType; this->update(); } } void LunarCalendarYearItem::setDate(const QDate &date, const QString &lunar, const DayType &dayType) { this->date = date; this->lunar = lunar; this->dayType = dayType; this->update(); } void LunarCalendarYearItem::setBorderColor(const QColor &borderColor) { if (this->borderColor != borderColor) { this->borderColor = borderColor; this->update(); } } void LunarCalendarYearItem::setWeekColor(const QColor &weekColor) { if (this->weekColor != weekColor) { this->weekColor = weekColor; this->update(); } } void LunarCalendarYearItem::setSuperColor(const QColor &superColor) { if (this->superColor != superColor) { this->superColor = superColor; this->update(); } } void LunarCalendarYearItem::setLunarColor(const QColor &lunarColor) { if (this->lunarColor != lunarColor) { this->lunarColor = lunarColor; this->update(); } } void LunarCalendarYearItem::setCurrentTextColor(const QColor ¤tTextColor) { if (this->currentTextColor != currentTextColor) { this->currentTextColor = currentTextColor; this->update(); } } void LunarCalendarYearItem::setOtherTextColor(const QColor &otherTextColor) { if (this->otherTextColor != otherTextColor) { this->otherTextColor = otherTextColor; this->update(); } } void LunarCalendarYearItem::setSelectTextColor(const QColor &selectTextColor) { if (this->selectTextColor != selectTextColor) { this->selectTextColor = selectTextColor; this->update(); } } void LunarCalendarYearItem::setHoverTextColor(const QColor &hoverTextColor) { if (this->hoverTextColor != hoverTextColor) { this->hoverTextColor = hoverTextColor; this->update(); } } void LunarCalendarYearItem::setCurrentLunarColor(const QColor ¤tLunarColor) { if (this->currentLunarColor != currentLunarColor) { this->currentLunarColor = currentLunarColor; this->update(); } } void LunarCalendarYearItem::setOtherLunarColor(const QColor &otherLunarColor) { if (this->otherLunarColor != otherLunarColor) { this->otherLunarColor = otherLunarColor; this->update(); } } ukui-panel-3.0.6.4/ukui-calendar/lunarcalendarwidget/statelabel.cpp0000644000175000017500000000170514203402514023741 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see buttons() == Qt::LeftButton){ Q_EMIT labelclick(); } return; } ukui-panel-3.0.6.4/ukui-calendar/lunarcalendarwidget/lunarcalendaritem.h0000644000175000017500000002164614203402514024766 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #ifdef quc #if (QT_VERSION < QT_VERSION_CHECK(5,7,0)) #include #else #include #endif class QDESIGNER_WIDGET_EXPORT LunarCalendarItem : public QWidget #else class LunarCalendarItem : public QWidget #endif { Q_OBJECT Q_ENUMS(DayType) Q_ENUMS(SelectType) Q_PROPERTY(bool select READ getSelect WRITE setSelect) Q_PROPERTY(bool showLunar READ getShowLunar WRITE setShowLunar) Q_PROPERTY(QString bgImage READ getBgImage WRITE setBgImage) Q_PROPERTY(SelectType selectType READ getSelectType WRITE setSelectType) Q_PROPERTY(QDate date READ getDate WRITE setDate) Q_PROPERTY(QString lunar READ getLunar WRITE setLunar) Q_PROPERTY(DayType dayType READ getDayType WRITE setDayType) Q_PROPERTY(QColor borderColor READ getBorderColor WRITE setBorderColor) Q_PROPERTY(QColor weekColor READ getWeekColor WRITE setWeekColor) Q_PROPERTY(QColor superColor READ getSuperColor WRITE setSuperColor) Q_PROPERTY(QColor lunarColor READ getLunarColor WRITE setLunarColor) Q_PROPERTY(QColor currentTextColor READ getCurrentTextColor WRITE setCurrentTextColor) Q_PROPERTY(QColor otherTextColor READ getOtherTextColor WRITE setOtherTextColor) Q_PROPERTY(QColor selectTextColor READ getSelectTextColor WRITE setSelectTextColor) Q_PROPERTY(QColor hoverTextColor READ getHoverTextColor WRITE setHoverTextColor) Q_PROPERTY(QColor currentLunarColor READ getCurrentLunarColor WRITE setCurrentLunarColor) Q_PROPERTY(QColor otherLunarColor READ getOtherLunarColor WRITE setOtherLunarColor) Q_PROPERTY(QColor selectLunarColor READ getSelectLunarColor WRITE setSelectLunarColor) Q_PROPERTY(QColor hoverLunarColor READ getHoverLunarColor WRITE setHoverLunarColor) Q_PROPERTY(QColor currentBgColor READ getCurrentBgColor WRITE setCurrentBgColor) Q_PROPERTY(QColor otherBgColor READ getOtherBgColor WRITE setOtherBgColor) Q_PROPERTY(QColor selectBgColor READ getSelectBgColor WRITE setSelectBgColor) Q_PROPERTY(QColor hoverBgColor READ getHoverBgColor WRITE setHoverBgColor) public: enum DayType { DayType_MonthPre = 0, //上月剩余天数 DayType_MonthNext = 1, //下个月的天数 DayType_MonthCurrent = 2, //当月天数 DayType_WeekEnd = 3 //周末 }; enum SelectType { SelectType_Rect = 0, //矩形背景 SelectType_Circle = 1, //圆形背景 SelectType_Triangle = 2, //带三角标 SelectType_Image = 3 //图片背景 }; explicit LunarCalendarItem(QWidget *parent = 0); QMap> worktime; QString handleJsMap(QString year,QString month2day); //处理js解析出的数据 protected: void enterEvent(QEvent *); void leaveEvent(QEvent *); void mousePressEvent(QMouseEvent *); void mouseReleaseEvent(QMouseEvent *); void paintEvent(QPaintEvent *); void drawBg(QPainter *painter); void drawBgCurrent(QPainter *painter, const QColor &color); void drawBgHover(QPainter *painter, const QColor &color); void drawDay(QPainter *painter); void drawLunar(QPainter *painter); private: bool hover; //鼠标是否悬停 bool pressed; //鼠标是否按下 bool select; //是否选中 bool showLunar; //显示农历 QString bgImage; //背景图片 SelectType selectType; //选中模式 QDate date; //当前日期 QString lunar; //农历信息 DayType dayType; //当前日类型 QColor borderColor; //边框颜色 QColor weekColor; //周末颜色 QColor superColor; //角标颜色 QColor lunarColor; //农历节日颜色 QColor currentTextColor; //当前月文字颜色 QColor otherTextColor; //其他月文字颜色 QColor selectTextColor; //选中日期文字颜色 QColor hoverTextColor; //悬停日期文字颜色 QColor currentLunarColor; //当前月农历文字颜色 QColor otherLunarColor; //其他月农历文字颜色 QColor selectLunarColor; //选中日期农历文字颜色 QColor hoverLunarColor; //悬停日期农历文字颜色 QColor currentBgColor; //当前月背景颜色 QColor otherBgColor; //其他月背景颜色 QColor selectBgColor; //选中日期背景颜色 QColor hoverBgColor; //悬停日期背景颜色 public: bool getSelect() const; bool getShowLunar() const; QString getBgImage() const; SelectType getSelectType() const; QDate getDate() const; QString getLunar() const; DayType getDayType() const; QColor getBorderColor() const; QColor getWeekColor() const; QColor getSuperColor() const; QColor getLunarColor() const; QColor getCurrentTextColor() const; QColor getOtherTextColor() const; QColor getSelectTextColor() const; QColor getHoverTextColor() const; QColor getCurrentLunarColor() const; QColor getOtherLunarColor() const; QColor getSelectLunarColor() const; QColor getHoverLunarColor() const; QColor getCurrentBgColor() const; QColor getOtherBgColor() const; QColor getSelectBgColor() const; QColor getHoverBgColor() const; QSize sizeHint() const; QSize minimumSizeHint() const; public Q_SLOTS: //设置是否选中 void setSelect(bool select); //设置是否显示农历信息 void setShowLunar(bool showLunar); //设置背景图片 void setBgImage(const QString &bgImage); //设置选中背景样式 void setSelectType(const SelectType &selectType); //设置日期 void setDate(const QDate &date); //设置农历 void setLunar(const QString &lunar); //设置类型 void setDayType(const DayType &dayType); //设置日期/农历/类型 void setDate(const QDate &date, const QString &lunar, const DayType &dayType); //设置边框颜色 void setBorderColor(const QColor &borderColor); //设置周末颜色 void setWeekColor(const QColor &weekColor); //设置角标颜色 void setSuperColor(const QColor &superColor); //设置农历节日颜色 void setLunarColor(const QColor &lunarColor); //设置当前月文字颜色 void setCurrentTextColor(const QColor ¤tTextColor); //设置其他月文字颜色 void setOtherTextColor(const QColor &otherTextColor); //设置选中日期文字颜色 void setSelectTextColor(const QColor &selectTextColor); //设置悬停日期文字颜色 void setHoverTextColor(const QColor &hoverTextColor); //设置当前月农历文字颜色 void setCurrentLunarColor(const QColor ¤tLunarColor); //设置其他月农历文字颜色 void setOtherLunarColor(const QColor &otherLunarColor); //设置选中日期农历文字颜色 void setSelectLunarColor(const QColor &selectLunarColor); //设置悬停日期农历文字颜色 void setHoverLunarColor(const QColor &hoverLunarColor); //设置当前月背景颜色 void setCurrentBgColor(const QColor ¤tBgColor); //设置其他月背景颜色 void setOtherBgColor(const QColor &otherBgColor); //设置选中日期背景颜色 void setSelectBgColor(const QColor &selectBgColor); //设置悬停日期背景颜色 void setHoverBgColor(const QColor &hoverBgColor); //五个字以上节日名称显示tooltip bool event(QEvent *event); Q_SIGNALS: void clicked(const QDate &date, const LunarCalendarItem::DayType &dayType); }; #endif // LUNARCALENDARITEM_H ukui-panel-3.0.6.4/ukui-calendar/lunarcalendarwidget/image/0000755000175000017500000000000014203402514022174 5ustar fengfengukui-panel-3.0.6.4/ukui-calendar/lunarcalendarwidget/image/bg_calendar.png0000644000175000017500000000624414203402514025131 0ustar fengfengPNG  IHDRHHUGgAMA a cHRMz%u0`:o_FbKGD pHYs  tIMEwXX][q1am JhE~3_98yppJ%H8("3?]NCw}Ꟗ֭y?e*j`@jr1Kӯ?W+RY?<0 sd۠\P@-_}k}xťE(3N Z06>(gDnN+fSR¶!erym5凯Ϳ~;R]ʸ`pOL_9?2Yn4r}nDI)pBZ +V}nbGZ *JݪrR9YLl`P[ϔgNMLWVV>^d$ /yڶh5q"< LJ'^^4\P//W~juw+=*$F*+.!#Q*/8Ƀϼ:=Jyz19IsmZ]tuDL@:T>;Rf~ة{{1XJlZӋiP!i@:T^yʎsL>Cg 3P( }z H @Kّ 8%[=Z] y8ΏA$|̂L@O˥#5g~U)5_y=m[s#b ʀ(hVŮLyFʉ7 ҀtgԞSJJМAH|xʶ+f"MSZfK9z"> 9#Dq`Ebj%K)z\LYy[~0`֣$ R̤\ (w>oEׁtp?YJ}u)3MuD5(dz$͌A]zWA VguT8[)1; Jұ%+1iN /ĐKGCC!?@@< <^.nLAdf1_Pew2%bG$w$[ Cv1ݢi(FQ,eXG) 6x~sN4ܑ{HO̐`@gM^3P JUdPib2.[hi@ڦvRFi+(?"R`^@)1Q }lrxr3(J= PfAng2s? nRO`Q(>Ȩ|F#J7&WPyZAAmp/ NIP wf!irFYU=]G]*ވA]_T+^,2'; \-KE; RP$Vlݰ =V)̞d.nzv:`oI*&EE{ p @+(ݍ$L@CylHWD 1$CtL4#YfTD* m _g cd][nsD+bӂuZhbP +-8+J}tXa*(8~(1!VTM4f &uZ{_baIxùRȂDp U D7o5DkZeZ{).r'm)+ P{i;ߔ|u?A:T@滎GG_i^aPKʟ-ub!"5[?m?] Ù*#m߽躿y "%k@2~ټZT.r|@"e=8ο4b@]dz(rͶ1csI_;"Xp ׽0/ Cfy[ʥm=m16Wb[GG{W{պ)`=dn#ẹ9߷wDD・owf gV}2KRem!, hȰYBt&7ApOp2imMR};Tu#BN^n~.>N^n~ / _!"""`%!@P`p 0@P`pd]YTC2 ߸ݺ  p%tF#fM',KLPXJvY#?+X=YKLPX}Y ԰.-, ڰ +-,KRXE#Y!-,i @PX!@Y-,+X!#!zXYKRXXY#!+XFvYXYYY-, \Z-,"PX \\Y-,$PX@\\Y-, 9/- , }+XY %I# &JPXea PX8!!Ya RX8!!YY- ,+X!!Y- , Ұ +- , /+\X G#Faj X db8!!Y!Y- , 9/ GFa# #JPX#RX@8!Y#PX@e8!YY-,+X=!! ֊KRX #I UX8!!Y!!YY-,# /+\X# XKS!YX&I## I#a8!!!!Y!!!!!Y-, ڰ+-, Ұ+-, /+\X G#Faj G#F#aj` X db8!!Y!!Y-, %Jd# PX<Y-,@@BBKcKc UX RX#b #Bb #BY @RX CcB CcB ce!Y!!Y-,Cc#Cc#-1]=/Ͱ 2/ְ Ͳ  +@ +@  + +@ +@ ++014>3!2!2#!"&463!&]$(($+@&&&&@+F#+&4&&4&x+++ͳ+)Ͳ+,/ְ$Ͱ#2$Ͱ/$!+"2ͰͰ/-+6+ #. #  " "#.... ..@(9!99!99014>32467632".4>32".Dhg-iW&@ (8DhgZghDDhg-iWDhgZghrdN+'3 8(2N++NdN+';2N++!P+Ͱ!/"/ְͰ+ ͱ#+$9  99! $9016$ #"'#"$&  oo|W%L46$܏r1ooܳ%54L&V|oMr*MI+ Ͱ"/5ͰK/N/ְͰ+2+B2 ͱO+5"9K&*$9015463!2#!"&73!265+".'&%&';2>767>5<.#!"^BB^^B@B^   %3@m00m@3% :"7..7":6] @  @B^^BB^^B  $΄+0110+$@t1%%1+;  /ְͰͱ+014632>32"'.>oP$$Po>4 #L~'T/ Ͳ  +  +2'/#(/ְͰͳ%+!Ͱ!/%ͱ)+!9%9990154>322>32#!"&6   6Fe= BSSB =eF6 yy@>ƒ5eud_C(+5++5+(C_due5xV> /?O_o /ͱSt22/|3#Ͱ2,/[333ͱc2254&'.7> $&462"&+i *bkQнQkb* j*zzLhLLhLBm +*i JyhQQhyJ i*+ mzz4LL44LL/?Ob/ ,3267676;27632#"/+"&/&'#"'&'&547>7&/.$264&" (C  ,/ 1)  $H  #H  ,/ 1)  ~'H Ԗ ..9Q $ k2 k w3 [20 6%2X  % l2 k r6 [21ԖԖ#/?GWg(+Ͱ!/.33ͱ@22E/ h/ְ$Ͳ$ +@ +$0+9Ͱ9H+QͰQX+aͰa-+Ͳ- +@ +i+0$99@9HEG99XQB9aA9-9!(43!2!2+#!"&5#"&3!2>5!46;2+"&!'&'!46;2+"&%46;2+"&5FN(@(NF5`^BB^`@@@`0 o@@@@ @%44%@LSyuS:%%@u  @@f!5=3+.36/"ְ2Ͱ2/++Ͱ2+Ͱ/7+/2'$9016762546;2#"' '&/465 #!!!"&  X  >  LL >??&&oWh J A J& &&#H/Ͱ/Ͱ/$/ְͰ+Ͱ+ ͱ%+9#901463!2#!"&7!!"&5!!&'&'8((`8(8((8`(8x @(8(`((88H8( 9  , /Ͱ*/Ͳ* +@! +/-/ְ Ͱ +&Ͳ& +@ +&+ͱ.+  $9& $9* $9 $901$  $ >. 546;46;2#!"&aa^(@a^(@`@2N1C*0+3(/5Ͱ?/D/E+(09901747>3!";26/.#!2#!26'.#!"3!";26'5.+"2$S   S$.@   @.  I6>  >6I     @  -5=u+1Ͱ82+Ͱ5/<3 Ͱ2>/ְ"Ͱ"3+7Ͱ7;+Ͳ; +@; +?+")*$93 .997&9 )*99015463!2?!2#!"&63!463!2!2"'&264&"264&"8(ч::(88(@(8E*&&*@6@L&4&&4&4&&4`@(8888((88'&&@')@*4&&4&&4&&4& 0m /Ͱ/1/ְ Ͱ +$Ͳ$ +@$( +$+ͱ2+  0$9$,-99 $9,$901$  $ >. 6;46;232"'&aa^(0  a^(^` @ 0m /Ͱ/1/ְ Ͱ ,+%Ͳ,% +@, +%+ͱ2+,  $9%99  $9($901$  $ >. 4762++"&5#"&aa^(. ?  @a^( ? `#%+Ͱ2+Ͱ /$/%+01547>3!2#!"&!!7!.'! 5@5 &&<_@_<<@>=(""=>&&   'F /Ͱ/(/ְ Ͱ +ͱ)+  $9$$901$  $ >. 476#"'&aa^( !  a^(2%J 3=0/"Ͳ"0 +"' +/4/ְͱ5+"999 99016$3276#!"'&?&#"3267672#"$&zk)'&@*hQQhwI mʬ8zoe*@&('QнQh_   z$G`/ Ͳ  +@  +2=/)Ͳ=) +@=E +52H/ְͱI+,/99  "#999=9),./999011463!23267676;2!"$'"&5!2762#!"&4?&#"+"&&&GaF * @hk4&Ak4&&@&ɆF * &&4BHrd nf&: Moe&@&&4rd/?O_oq +Ͱ-/\3$ͰT2=/l34Ͱd2M/|3DͰt2//ְͰ +0@22)ͱ8H22)+ ͱ+)PX`hpx$9015463!2#!"&73!2654&#!"546;2+"&546;2+"&546;2+"&5463!2#!"&5463!2#!"&5463!2#!"&^BB^^B@B^   @  @  @  @  @  @  @    @    @    @ @B^^BB^^B  @  @@  @  @  @  @  @  @  @  @  @  @  @ O+ͱ 22/  /ְͲ +@ ++ Ͳ  +@  +!+ 9901546;54 32#!"&!54&"8( p (88(@(8@Ԗ`@(88((88jj@7X1/Ͱ#2 ,Ͳ, +,5 +8/ְͰ ͱ9+9999$901462+"&5&476763232>32#".#"#"&@KjK@ @ @:k~&26]S &ך=}\I&5KK5H&  & x:;*4*&t,4, &KkA+3+/L/ְ.Ͱ.D+42=Ͱ=+Ͱ 2'+ ͱM+D.H9=*+$9' 9+A 990146$ #+"&546;227654$ >3546;2+"&="&/&4L4<X@@Gv"DװD"vG@@X<zz藦1!Sk @ G< _bb_ 4.54632#"&&M4&&4&""""& FUUF &&M&&M&*.D.%%G-Ikei/`/l/ְ'Ͳ' + +2'5+CͲ5C +5. +;2CT+eͲTe +TJ +]2m+`i +>G"$901463!62"'!"&%4>4.54632#"&4767>4&'&'&54632#"&47>7676'&'.'&54632#"&&M4&&4&""""& FUUF &d'8JSSJ8'& &e'.${{$.'& &&M&&M&*.D.%%'66'&;;&$ [2[ $&[4[&  #'+/37+,4333ͱ-522/3Ͱ /Ͱ /ͱ22"Ͱ/$3 Ͱ(2/03Ͱ12/*3Ͱ%28/ְ2Ͱ 2+2Ͱ2 + 2Ͱ2+$2#Ͱ(2#,+ 022/ͱ222/4+)227ͱ&229+011!!!!!!5353!353!5#!%!!535353 #'+/37;?4+@<  $(,08$3@/ְͰ+Ͱ+ Ͱ  +Ͱ+Ͱ+Ͱ+Ͱ+Ͱ +#Ͱ#$+'Ͱ'(++Ͱ+,+/Ͱ/0+3Ͱ34+7Ͱ78+;Ͱ;<+?ͱA+011373333333333333333333333333333? ?~_>_  ^?^??????_^ ?./Ͳ +@ +/ְͲ +@ ++01463!2#"'.264&"L45&%%'45%5&5KjKKj`4L5&6'45%%%%JjKKjKk5J/Ͱ2 +@ +6/ְͲ +@ +0+%ͱ7+0*-$901463!2#"'.264&"%32#"&'654'.L45&%%'45%5&5KjKKj5&%%'4$.%%5&`4L5&6'45%%%%JjKKjK5&6'45%%%54'&5 yTdty@+PͰ:/XͰa/hͰq/1Ͱ,2u/v+6=7>76&7>7>76&7>7>76&7>7>63!2#!"3!2676'#!"&'&3!26?6&#!"73!26?6&#!"  ,*$/ !'& JP$G] x6,&(sAeM `   > `   .  &k& ( "$p" . #u&#  %!' pJvwEF#9Hv@WkNC  @   @  /ְ Ͱ ͱ+01546763!2#"' #"'.'!!''!0#GG$/!' "8 8""8  X! 8'+4<o(+ Ͱ+/,Ͱ $38Ͱ+4.901546;463!232+#!"&=#"&!!!#"&=!264&"qO@8((`(@Oq 8(@(8 (8&4&&4Oq (8(`(qO` (88(8(Z4&&4&!)n/Ͱ)/%Ͱ!/ */ְͰ#+'Ͱ'+ͱ++9'# !$99%)$9 !99901546;7>3!232#!"&  462"j3e55e3jjjrgj1GG1jjrHPY'+3FͰF $A333Ͳ&=2224/KQ/R+F!?D$9'947999K9017>7;"&#"4?2>54.'%3"&#"#2327&'B03& K5!)V?@L' >R>e;&L::%P!9&WaO 'h N_":- &+# : ' 5KaQ+0Ͳ+Ͱ[/@Ͱ/63ͰJ b/ ְ`Ͱ92 ` +@  +2`S+*ͰE !ͱc+` 3699E0JNQ[$9S'9[Q *99@'9!E999017>7><5'./6$3232#"&#"32>54.#"3 4'.#"$ $5.3b[F|\8!-T>5Fu\,,jn*CRzb3:dtB2KJBx)EB_I:I^ %/2+ S:T}K4W9: #ƕdfE23j.?tTFi;J] OrB,+  )# + +)$)#+%)#+&)#+')#+()#+ #99()#9'9&9%9$9@ % #$&'()...........@ % #$&'()...........@/5799- 999017>7676'5.'732>7"#"&#&#"$ zj=N!}:0e%  y + tD3~U'#B4 # g  '2 %/!: T bRU,7a}(/%*-Y$3 Ͳ( +@({ +=D22 ( +@ m +22~/ֱM+2Ͳ2M +@2; +M2 +@MF +2e+tͱ+MD992A99e =bi$9tlmz{$9 (&9017326323!2>?23&'.'.#"&"$#"#&=>764=464.'&#"&6;#"&?62+32"/Q6 ,,$$% *'  c2N  ($"LA23Yl !x!*o!PP!~:~!PP!~:~ pP,T NE Q7^oH!+( 3  *Ueeu  wgn%%%%ao+Ͳc+z+Y/ '33/ְb2Q+*Ͳ*Q +@*8 +Q* +@QC +*+Ͱ|2+QAIYlo$9*>9@ ':prv$9 z999o99Y@ $<`fiv$901732632$?23&'.5&'&#"&"5$#"#&=>7>4&54&54>.'&#"&47>32!4&4>32#".465!#".'Q6 ,,Faw!*' =~Pl*  ($"LA23Yl  )!* @7<  <7@@7<  <7@ pP,T MF Q747ƢHoH!+( 3  tJHQ6  wh86,'$##$',686,'$##$',6/?& +Ͱ/Ͱ-/$Ͱ=/4@/A+01=463!2#!"&5463!2#!"&5463!2#!"&5463!2#!"&&&&&&&&&&&&&&&&&@&&&&&&&&&&&&&&&&/?& +Ͱ-/$Ͱ/Ͱ=/4@/A+01=463!2#!"&5463!2#!"&5463!2#!"&5463!2#!"&&&&&&&&&&&&&&&&&@&&&&&&&&&&&&&&&&/?& +Ͱ-/$Ͱ/Ͱ=/4@/A+01=463!2#!"&5463!2#!"&5463!2#!"&5463!2#!"&&&&&&&&&&&&&&&&&@&&&&&&&&&&&&&&&&/?& +Ͱ/Ͱ-/$Ͱ=/4@/A+01=463!2#!"&5463!2#!"&5463!2#!"&5463!2#!"&&&&&&&&&&&&&&&&&@&&&&&&&&&&&&&&&&/?O_oR +L3ͰD2/\3ͰT2-/l3$Ͱd2=/|34Ͱt2/ֲ 0222 Ͳ(8222+01=46;2+"&546;2+"&546;2+"&546;2+"&5463!2#!"&5463!2#!"&5463!2#!"&5463!2#!"&         @   @   @   @                  /?O6 +Ͱ=/,34ͰM/DͰ%2/P/Q+M4! 9901=463!2#!"&5463!2#!"&47632#"' 5463!2#!"&5463!2#!"&   @    @      W @   @              /?O6 +Ͱ=/34ͰM/DͰ2-/$P/Q+M49901=463!2#!"&4632#"&5463!2#!"&5463!2#!"&5463!2#!"&   @        @  @   @    @         + /!+01463!2632#"'#!"&ww '' mw@w ww**w&.i+ Ͱ./*Ͱ///ְͰ(+ 2,Ͳ,( +@,& +,+ ͱ0+,("9#9. "#%$9*$9015463!2#!"&73!2654&#!"5 462"^B@B^^BB^ @  @ppp B^^B@B^^B    @`@pppk %3+Ͱ&/ְͰͱ'+ 9 901 337'7327654#"7632@k[[  V$65&%%@`[[ &&'45%? /Ͱ//ְͰ+ͱ+ $999014 "&'&$264&",,!?H?!Ԗ,mF!&&!FԖԖ G /Ͱ//ְ Ͱ +ͱ+  99 99$901$  $3"aa^a^@-I+Ͳ +@ +./ְͰ+ͱ/+9 999 990147>7>2 %2654'.'&"QqYn 243nYqQXKjK" ]""]ً ,T5KK5$!+!77!+!*/6>H}(+Ͱ+/0Ͱ2Ͱ/I/ְͰ++2Ͱ0Ͱ2+$ͱJ+2 /457$9$-;?9990(9@ !,-.458;547632#"'&=# #"'.w M8 pB^^B@B^ww#;Noj'  'sw- 9*# @w "^BB^^B  w1T`PSA:'*4*  "g`/DY-+Ͳ- +$ +/3E/ְͰ+)ͱF+ 07A$97=A9999:9901463!2#"'&#!"3!26=4?632#!"&4?62 62"'w@?6 1 B^^B@B^ @ wwnBBnBR @w 1 ^BB^^B @ w6BnnBCv=/*3Ͱ2= +@=A +&2= +@ +2D/;ְ 2,Ͱ2,; +@,0 +2;, +@;8 + 2E+,;34$9="#$9014762!#"&4762+!5462"&=!32"'&46;!"'4&&4&&44&&4&&4f4&&44&&4&&44&&/ְͰ2+0146;2676'&'+"&&& : &&@&&Z  @  Z&&+,/ְ%Ͱ2-+0146;2676676'&''&'+"&&&  : : &&@&&Z  :  @  :  Z&&z476676'&''z::f4 :  @  : | 46&!0!`  $   /ְ Ͱ +ͱ!+01463!2#!"&%463!2#!"&&&&&&&&&@&&&&&&&& /Ͱ/ְ Ͱ ͱ+01463!2#!"&&&&&@&&&&4646&5&::` :  :4:  : +,/ְ2ͱ-+01464646;2+"&5&5&&&&&::` :  : &&&& :  : /ְ2ͱ+014646;2+"&5&&&&&:` : &&&& :  +/+017463!2#!"&&762#!&&&& 4 @@&&&&:4762 "'44444Zf647 &4?62"/Z44f444 /B /Ͱ'/0/ְ Ͱ +ͱ1+  $9'$901$  $3!;265!26=4&#!4&+"!"aa^r&&&&&&&&a^&&&&&&&& I /Ͱ//ְ Ͱ +ͱ+  $9 999901$  $3!26=4&#!"aa^r&&&&a^&&&& 7R /Ͱ2-/'38/ְ Ͱ22 +"2ͱ9+  5$9-*$901$  $32?32?654/7654/&#"'&#"aa^ZZZZa^PZZZZ #Q /Ͱ/Ͱ $/ְ Ͱ +ͱ%+  $9 99999901$  $327654/&"'&"aa^.j[4h4[a^ZiZ 6Fg /:ͰC/$Ͱ5/G/ְ7Ͱ 27 +@7 +71+ͱH+7 $91 5>$9$C9959901$  $32767632;265467>54.#";26=4&+"aa^  5!"40K(0?i+! ":oW_a^]d D4!&.uC$=1/J,XR  *:B /Ͱ/.Ͱ7/;/ְ Ͱ 2  +@ & ++2<+$901$  $%3!26=4&+4&#!";#";26=4&+"aa^2```a^R/_4-/0?333ͲGW222`/(ֲ3S222!Ͳ;K222a+01546;>7546;232++"&=.'#"&546;2>7#"&=46;.'+"&=32#&%&&%&&%&&%&S l&&l m&&m l&&l m&&@&%&&%&&%&&%&&l m&&m l&&l m&&m l&& ;F /Ͱ/. 4?'&4?62762"/"/aa^(;     a^(     ,F /Ͱ/-/ְ Ͱ +ͱ.+  %$9!)$901$  $ >. 4?6262"'aa^(f44fZ4a^(X4ff4Z&"F /Ͱ/#/ְͰ + ͱ$+  $9 "$9016$  $&&#"32>54'z8zzfY󇥔eoɒVW:zzzzO[YWo@5K / !/"+ 90147632!2#!#"'&@%&54&K&&4AA4@%&&K%54'u%@4'&&J&j&K55K$l$L%%%5K /!/"+9015463!&4?632#"/&47!"&A4&&K&45&%%u'43'K&&%@4A5K&$l$K&&u#76%u%%K&j&%K5K@!"/ְͱ#+90147632#"'+"&5"/&5&#76%%%K&56$K55K$l$K&55&%%u'43'K&&%@4AA4&&K&5K"#/ְͱ$+9014?63246;2632#"'&5&J'45%&L44L&%54'K%%u'45%u&5&K%%4LL4@&%%K'45%t%%$,O/Ͳ +% +@ + +@ +-/)ְ"Ͱ"Ͱ/.+")%9 990147!3462"&5#"#"'.'5&44&bqb>#  dž&4& 6Uue7D#  "/46262#!"&47'&463!2"/"/&4L  r &@& L&&&4  r@&L r  4&&m L4&&@& r s/647'&463!2"/"/46262#!"& L&&&4  r&4L  r &@& L4&&@& r&L r  4&&#J+!/3Ͱ2! +@ +$/ְ2Ͱ 2 +@ + +@ +%+015463!46;2!2#!+"&5!"&8(8((8(88(`8((8`(8`(8(88(`8((8`(88(8 /Ͱ/+015463!2#!"&8((88(@(8`(88((88z56//ְ 2(Ͱ27+0167-.?>46;2%6 '%+"&5&/m. .@g. L44L .g@. .@g.L44L.g@egg.n.34LL4͙.n.gg.n.4LL43.n -0 /!Ͱ*/Ͱ/.//+*999901$  $;2674'&+";26=4&+"aa^    a^  m /  @*3AJ#+7Ͱ(/3Ͱ2/>3.ͰB22/H3 Ͱ2K/&ְ4ͳ4&+,Ͳ, +@ +4;+ͳ;+FͰF/ͲF +@ +L+;, /B$9F&992. $901463!"&46327632#!2+#!"&5#"&;'&#";26=5!3264&#"]]k==k]]`8((8`x8(~+($$(88(+ @MM`(88(vP88,8P89Oh1+J/P/ ְ:Ͳ : +@ +:Ͱ/:H+ ͱQ+:,/99H'99 9J1 ',=$9 990154>54&'&54>7>7>32#"'.#"#".'.327>76$3264&#">J> Wm7' '"''? ./+>*&^&&zy#M6:D 35sҟw$ '% ' \t&_bml/J@L@ N&^|h&4&c3.+ /4/5+01463!2#!"&54>54'''. @  1O``O1BZZ71O``O1CZZ7  @  `N]SHH[3^)TtbN]SHH[3`)Tt!1H +Ͱ/%Ͱ//2/ְ"ͱ3+" 9% $9/ $901476  '7 $7&' 547265463264&#"ٌ''l==8(zV}D##D#EuhyyhulVz(#-=OUq>+?Ͳ+;/Ͳ; +@ +V/*ְ2.Ͳ.* +@. +W+.* &,999?> 99;@ &0,EJPQ$999901476!27632#"'&547.'77.547265463264&#"76$7&'7 Y[6 $!i\j1  z,XlNWb=8(zV}0Jiys?_9'Fu>La   YF  KA؉Eu?kyhulVz(Äsp@_"F"@Q-'#3 /'Ͱ0/Ͱ /4/5+017>2#!"&'&;2674'&+";26=4&+"#"'&' +&/& `  L4,@L 5 `   a 5 L@,4LH` `  #'+/?CGKOSWgkos!/$Ͳ@Lh222'/BNj333(ͲDPl222+/FRn333,ͲHTp222//JVr333ͱ223Ͱ[2Ͱ2J> +@J" +>J +@> +r/s+7M^_999J /CO$9>A99901=46;2>767>3!54632#"&=!"+"&546;2.+"&673!54632#"&=".0N<* .)C=W]xD ?  0N<* .)C=W]xDmBZxPV3!   mBZxPV3!\-7H)O]-7H)   ".=&' +'/ְ Ͱ ͱ(+ $99014>$32#"'&'5&6&>7>7&LdFK1A  0) e٫C58.H(Y#3CR!/Ͳ! +@ +21/@3(Ͱ82D/ְ$2 Ͱ,2 +42Ͱ<2E+  !99015463!22>=463!2 $463!2#!"&%463!2#!"&&&/7#"462"$462"& & &&&%ZKjKKj5KjKKj4& %&%z 0&4&&3D7KjKKjKKjKKjK+/+015463!2!2#!"&\@\\\@\\\ \@\W*-(+Ͱ/ Ͳ  +@  ++/,+(9015463!2!2!"4&47>3!2#!"&\@\ \^=IP+B@"5+B"5\\ \_Ht#3G#t3G@; /ְͲ +@ +2 +@ +2!+ $901646;#"&4762+32"'@&&4&&4&4&&44&&4@;/Ͳ +@ +2 +@ + 2 /!+$9014762!5462"&=!"'4&&44&&4f4&&4&&#'+/v+ Ͱ /$(,333!Ͳ! +@!% +@!) +@!- +/0/ְͰ +#Ͱ#$+'Ͱ'(++Ͱ+,+/Ͱ/+ ͱ1+015463!2#!"&73!2654&#!"!3!3!3!^B@B^^BB^ @   B^^B@B^^B    @[ /Ͱ$/Ͳ$ +@$? +A/ְ3Ͱ.23+ͱB+39"0=?$9 99$9015463!2#!"&%32>54'6767&#".'&'#"'#"www@wpČe1?*8ADAE=\W{O[/5dI kDtww@w^GwT -@ (M& B{Wta28r=Ku?RZ$X!/ 3Ͱ2/3Ͱ/%/ְ!Ͱ2! +2 Ͱ Ͱ/&+!9 99015463!2+37#546375&#"#3!"&www8D`Twww@w`6: &.>+ Ͱ/"Ͱ./2ͰaԖ68(B^5KK55KK5v@>ԖԖ(8^H1G^//5Ͳ/5 +@/* +@/H/ְ3Ͱ3>+ͱI+>3-/999 95/ -$9@ $9014$327.54632#".'#"'#"&2654'3264&"&#"2̓c`." b PTY9b '"+`N*(app)*Pppp)*P2ͣ`+"' b MRZBb ".`(*NppP*)pppP*)ck546?67&'&547>3267676;27632#"/+"&/&'#"'&547>7&/.$264&"54767&547>32626?2#"&'"'#"'&547&'&54767&547>32626?2#"&'"'#"'&547&'&2654&"2654&" "8x s"+  ")v  <  "8w s%(  ")v  > Ԗj 3>8L3)x3 3zLLz3 3>8L3)x3 3zLLz3 KjKLhLKjKLhL% #)0C vZl. Y L0" #)0C wZ l/ Y N,&ԖԖq$ ]G)FqqG^^Gqq$ ]G)FqqG^^GqV5KK54LL5KK54LL%OoN+&Ͳ:+ /P/ְͰ.+3ͱQ+&(L999.069939CD999&N69L$9 99 .03$90146$ #"'#"&'&4>7>7.32$7>54''&'&'# E~EVZ|$2 $ |h:(t}| $ 2$|ZV쉉X(  &%(HZT\MKG{xH(%& (X08m/C+(Ͳ-+9Ͱ32m/ͰW/Ͱ^/n/ְ2Ͱ26+9Ͱ9[+Ͳ[ +@[X +F+#ͰK Q3!ͰN Ͱ#T+ͱo+6=_+   a_  +a`a_+ #9`a_9 _`a...... _`a......@62.9[9+-A$99#FL9N9m9#7FT$99f9^[c$9015463!6767>763232+"&'&#!"&6264&"32;254'>4'654&'>54&#!4654&#+K5$e:1&+'3TF0h1 &<$]`{t5K&4&&4 %/0Ӄy#5 +N2`@`%)7&,$)' 5KK5y*%Au]cgYJ!$MCeM-+(K4&&4&IIJ 2E=\#3M:;b^v+D2 5#$2:p0$/JͰ/QͰ//;Ͱp/93Ͱf/ q/ְ4Ͱ48+pͰpM+ͲM +@MP +^+W2Ͱb Ͱ^Z ͳT^+ͱr+6?m+ *(GI*)*(+GHGI+HGI #9)*(9()*GHI......()*GHI......@849Mp$/h$99b\9Z9J-FM$9Q.C99;T99p5b$901463!27>;2+#"'.'&'&'!"&264&"322654&5!2654&'>54'64&'654&+"+K5 tip<& 1h0##T3'"( 0;e$5K&4&&4 ')$,&7)%`@``2N+ 5#bW0/% 5K(,,MeCM$!JYgc]vDEA%!bSV2MK4&&4&$#5 2D+v^b;:M3#\=E2 JIURI@47%63#"&547&8?Vy% I) b955/(3Ͱ 2:/ְͰ#+ͱ;+# $9014632>32"'.7 654.""'.">oP$$Po>4 #LHexh\`C++I@$$@I+Z$_dC/Q|I.3MCCM3.I| (@F&+Ͱ>/-Ͳ>- +@>: +-> +@-2 +/A/ְͱB+->569901463!2#!"3!:#!"&463!462"&5!"&w@  B^^B   w&&4 4&@& w   ^B@B^   & &4& &5 /ͱ *22 +@' +//Ͱ 33Ͱ6/ְͰͰ+ Ͱ !+*Ͱ*++ ͱ7+99 99!1299*/39919015463!2#!"&;265."3#347>3234&#"35#www@wG9;HFtIf<,txIww@w3EE34DD@J&#1ueB".~ /3ͱ%22  +@  +/+33 //ְͰͳ+#Ͳ# +@ ++(Ͱ(/Ͳ( +@ +(+ͱ0+(#9901463"&463!2#2#!+"'!"&2654&"c4LL44LL4c&S3 Ll&@{LhLLhL{& &z'?a%+Ͳ% +@ + /@/ְͲ +@ ++!ͱA+()-.<$9!+9 +7:<$901463!2#!"3!26546;2#!"&47'&463!2"/"/w@B^^B@B^@ww &&&4t  r @w@^BB^^B@w 4&&&t r@F<+Ͱ/Ͳ +@ + +@ +%/3A/ ְ8ͱB+ 9901463!462"&5!"&>3!2654&#!*.54&>3!2#!"&54&&4 4&@&~ @B^^B  @ww & &4& & ^BB^   w@w ;BI(//Ͱ 2B/G3Ͱ2B +@ +J/ְ<Ͱ<2+Ͳ2 +@ +#H222 +@2 ++A22F+ͱK+2<7?99FC99B/8?C$9015463!5463!2!232#!"&=4632654&'&'.7&5!>=!8( ^B@B^ (8Sq*5&=CKuuKC=&5*q͍SJ6(8`B^^B`8(GtO6)"M36J[E@@E[J63M")6OtGNN`YaipxW/ 3MͰ/3{ͱ22`/\Ͱ%//ְ.Ͱ.^ ZͰZ/^Ͱ.+ͱ+ZAF99^@+,454'6'&&"."&'./"?+"&6'&6'&&766'&6'7436#6&76www 49[aA)O%-j'&]]5r,%O)@a[9( 0BA; + >HCw  $  /    61=ww@wa-6OUyU[q ( - q[UyUP6$C +) (  8&/ &  A   )    /7?p3+:3ͰͰ7/>3 Ͱ2@/,ְ%Ͱ%5+9Ͱ9=+Ͳ= +@= +A+%,995 0999 9 ()9901463!3!267!2#!"&&762#!#!"&5!"264&"264&"8(c==c(88(@(8E6*&&**&4&&4&4&&4 @(88HH88((88'@'(@&&4&&4&&4&&4&2d*/$3;ͰA2;> 'Ͱ[/ ͰX U3 Ͱ2e/0ְ6Ͱ- 39Ͱ326G+ͰN Q3ͱ22f+6^+ LJ+Â+ +LKLJ+ #9KLJ9JKL.......JKL......@N6 *$;AS[$9X>-39GQ$9 S9014>76763232632#"&#"#"&54654&732632327>54&'.54654'&#"#"&#"$IVNz<:LQJ  |98aIea99gw   N<;+gC8A`1oζA;=N0 eTZ  (:7,oIX(*()W,$-,-[% 061IO4767>3232>32#".'&'&'&'.382W# & 9C9 Lĉ" 82<*9FF e^\3@P bMO0# -\^e FF9*<28 "L 9C9 & #W283 #0OMb P@3* +Ͱ/ /ְͰ+ ͱ!+01463!2#!"&73!2654&#!"w@www^B@B^^BB^ @wwwwB^^B@B^^B#D#/Ͳ# +@# +2$/ְͰ!+ ͱ%+9!9 901546763!2#"' #"'.77!'!!''!0#GG$/!'YY "8 8""8  X! 8AUUjUN /!ͰQ/ͲQ +@Q4 +V/ְͰ&+ Ͳ& +@&A +W+&F9Q!09015463!2#!"&3267654'./.#"#".'.'.54>54.'.#"www@w <90)$9G55 :8 c7 )1)  05.Dww@w`$)0< D.50 + AB 7c  )$+ -.1 ,T17327.'327.=.547&546326767# ,#+i!+*pDNBN,y[`m`%i]]C_LҬ}a u&,SXK &$f9s? (bEm_@/3Ͱ2 +@ + //ְ2Ͱ 2 +@ ++01!54632#"!#!_ЭQV<%'w(ں HH RH /S/ְ)Ͱ)+ͱT+)54'6'&&"."&'./"?'&aa49[aA)O%-j'&]]5r,%O)@a[9( 0BA; + >HCaoMa-6OUyU[q ( - q[UyUP6$C +) (  8&/ &fM%f#+Ͱ2/ Ͳ +@ +&/ְͲ +@ + +@ ++ ͱ'+ 99#99015463!54 +"&54&"32#!"&8(r&@&Ԗ`(88(@(8`@(8&&jj8((88#'+V+ Ͱ$/(3%Ͱ)2/Ͱ /,/ְͰ2$+'Ͱ'+2 ͱ-+'(*99015463!2#!"&73!265!!54&#!"5!35!^B@B^^BB^ @   B^^B@B^^B  `  !=Y+233Ͳ +@ +;/'>/ֱ"22ͱ?+;99799;:999')901<62"5476;+"&'&'.5476; +"&'&$'.pppp$qr $!ߺ % }#pppp rqܠ!E$ ֻ!# %%/7?+Ͱ7/>33Ͱ:2"/&Ͱ'2,/@/ְͰ1+5Ͱ59+=Ͱ=+ͱA+6<7+ &./#7+ '.(   (/...... &'(/........@01547>3!2#!"&73!2654&#!"7!.#!"462"6462"\77\^B@B^   @ 2!/B//B/B//B@2^5BB52B^^B  @    B//B//B//B/.4B5/)ְͲ) +@) +1+Ͱ 2ͱ6+)$91 /$9015463! 22##%&'.67#"&%^B4L5KK5L4_u:B&1/&.- zB^yvB^L4KjK4L[!^k'!A3;):2*767>32!2+#"'&#!"&6264&"323254'>4'654&'!2654&#!4>54&#"+K5 A# ("/?&}vhi!<;5K&4&&4 HQ#5K4LN2$YGB (HGEG 5K J7R>@#zD9eME;K4&&4&@@IJ 2E=L43M95S+C=,@QQ93ksF+&Ͳ"+JͰn21/7ͰM/Ͱi/Ͱ`/ t/ְ4Ͱ4)+CͰ, ?Ͱ82C)+cͲc +@ch +CK+mͰmq+ͱu+,4/099?;9C)=99Kc" &F$9qm!991J*=Cr$97;9M499RWf999`Zc$901463!&546323!2#!"#"&?&547&'#"&73!32>;#".'.'&'&'.#"!"264&"hv}&?/"( #A  5KK5;=!iL4K5#aWTƾH #A<(H(GY$2N&4&&4gR7J K55K;ELf9>h4L=E2 JI UR@@2*!Q@.'!&=C+S59M4&&4&2`hh+?Ͱ/dͰ^/Ͳ^ +@^Y +K/Q3ͰF ͰU/ i/ְ3Ͱ3+YͰY# +>Ͱ>Q+ Ͱ ?+e2ͰD +ͱj+3/6\$9>Y U99 QN9?FLa$9hd"99^?#D$99FLN99U 9901463246326326#!"&54.'&'.7!54>54#"."&#"4&#"".#"264&"zD9eME;K55K J7R>@#,@QQ9@@IJ 2E=L43M95S+C=&4&&4}vhi!<;5KK5 A# ("/?&B (HGEG HQ#5K4LN2$Y4&&4&3hp+/@Ͱ#/JͰD2 NͰ1/7Ͳ71 +@7< +V/lͰp/q/ְ4Ͱ4.+=Ͱ= +XͰXC+(Ͱ(U+m2ͰQ +ͱr+.417c$9=:9X+@99(CF9U!HNi$9#@'9JF9N /H99V7Q$9pl99014>767>5463!2/#"'#"&5#"&732>3326532726732654.=!264&"#@>R7J K55K;ELf6Aig6Jy=C+S59M34L.9E2 JI UR@@2*! Q@.'!&&4&&4&?/"( #A  5KK5;=ihv}GY$2NL4K#5#aWTƾH #A<(H(4&&4& +B /Ͱ(/,/ְ Ͱ +ͱ-+  $9($901$  $2?64/!26=4&#!764/&"aa^-[j6[&& [6[a^M6[[6&&4[[ +B /Ͱ!/,/ְ Ͱ +ͱ-+  $9!$901$  $3!27764/&"!"aa^2&[6j[[6[ &a^&4[j[6[j[6& +B /Ͱ(/,/ְ Ͱ #+ͱ-+#  $9($901$  $2?;2652?64''&"aa^.[6&&4[[6[a^N6[ &&[6j[[ +B /Ͱ"/,/ְ Ͱ +ͱ-+  $9"$901$  $2?64/&"4&+"'&"aa^.j[6[j[6&&4[a^L6[[j6[&& [ $  $76.7"7"#76'&'.'2#22676767765'4.6326&'.'&'"'>7>&&'.54>'>7>67&'&#674&7767>&/45'.67>76'27".#6'>776'>7647>?6#76'6&'676'&2>767676&67>?&'4&'.'.'."#&6'&6&'3.'.&'&'&&'&6'&>567>#7>7636''&'&&'.'"6&'6'..'/"&'&76.'7>767&.'"67.'&'6.'.#&'.&6'&.5aa^ +  !       $     "  +       &"      4   $!   #          .0"2Α      a^   ' -( # * $  "  !     * !   (                                 P $      2 ~ /P+ Ͳ+0/ְͰ+!Ͳ! +!) +! +1+ 999!901347#"/&6264&"32>32#"&'bV%54'j&&4&&4:,{ /덹5&b'V%%l$4&&4&r! " k[G'C/37;R +4Ͱ7/Ͱ/0Ͱ3/Ͱ,/8Ͱ;/%990132327#"&462"4>322>32#!"&6  462"654'32>32+&|Kx;CBQgRpԖ 6Fe= BPPB =eF6 yy@>ߖԖgQBC;xK|pRga*+%u{QEԖԖ5eud_C(+5++5+(C_due5xV>ԖԖu%+*NQ{p%Gi/MͰW/Ͱ+ "ͰC/j/ְ&Ͱ&>+ Ͱ HͰ R+ͱk+& " h99RM999"MRY$9+ 99W -99C &$9014?632632#"/&547'#"/7327.54632654/&#"32?654/&#"#".'USxySSXXVzxTTUSxySSXXVzxTl)* 8( !(')((* 8( !SSUSx{VXXTTSSUSx{VXXT( (8 *(('(  (8 7+Ͳ+Ͳ+ /ְͰͱ+  9901467&5432632#!"t,Ԟ;F`j)6,>jK?чs !M/Ͱ/33 "/ְͲ +@ ++Ͳ +@ +#+9901&7#"&463!2+#!!'5#E8@&&&&@8EjY&4&&4&qY%q%FTbp~6+C KͰR/Ͱ/Ͱr2/YͰ`//ְͰ2+kl99R6<9999cjkl$9 .p$9Y #ow$9` mn999017>76326?'&'#"'.'&67632632 #"'#"'&6327>'&#"3276&'&#"7''54?'462"7bRSD zz DSRb)+USbn  NnbSVZ2.'Jd\Q2.'Jd\2Q\dJ'.2Q\dJ' ``!O&4&&4TFL5T II T5L;l'OT4M01B@#$rr$#@B10M5TNTЄ*$;3*$;3;$*3;$` @@Qq: $/4&&4&y@-09</1Ͱ/ Ͱ9/:Ͱ-/.Ͱ4/Ͱ(/=/ְ Ͱ /+)Ͱ) +!21Ͱ1&+ Ͱ ; +5Ͱ52+ͱ>+/ .9&1:9.-&<99 9(09015467>3!263!2#!"&5!"&7!467!#!7!!!#!7!(`((8D<(88(@(8(8(<8(`U+8(`U+(`(8((8(@(88( 8H(`<`(8+U`(8+||?w;/Ͱ /3Ͱ/@/ְͰ0+#Ͳ#0 +@#( +#+8ͱA+#099+3;$9  +08$93999014632#"'&#"32654'&#"#"'&54632#"'&ܟs] = OfjL?R@T?"& > f?rRX=Edudqq = _MjiL?T@R?E& f > =XRr?buds15Ed+233Ͱ5/Ͱ+/9Ͱ1/'A33F/ְͰ/+26Ͱ2Ͱ6=+(Ͱ(3+Ͱ+ ͱG+01463!2#!"&73463!234&'.##!"&5#!!;2654&+"8((`(8((88(@(8 08((8   @(8(`(`(88H(88(`1  `(88(  @  5463!2#!"&www@www@w/ +Ͱ/Ͱ-/$0/1+01=463!2#!"&5463!2#!"&5463!2#!"&&&&&&&&&&&&&@&&&&&&&&&&&&@'7Gl%+Ͱ Ͱ5/,Ͱ  ͰE/<Ͱ H/ֱ22ͱ 22I+%$9,5 $9E9901<62"462"462"5463!2#!"&5463!2#!"&5463!2#!"&ppppppppppp   @    @    @ 0ppppppppppp`      <L\l|Z+QͰ22Q1Ͱ/Ͳ%+7+;/!Ͱ/ͰͰj/aͰ /Ͱz/B3qͰDͰ@2Dz +@D> +}/ֱ 22ͳ0+1Ͱ1/=30ͰE+@Ͱ52E@ +@EC +@E++3Ͱ328 $Ͱ$/8ͱA228Ͱ/~+01 'L$9E&J99@ !);>$9Z!899Q'599/+4999aj $9  9014>54&#"'>32353!&732654'>75"##5!#"733!5346=#5463!2#!"&5463!2#!"&5463!2#!"&/BB/.#U_:IdDREi919+i1$AjM_39K!.EO\$9R1P$9 E;OR999%1$99015463!2#!"&476!2/&'&#"!&'&&?5732767654'&'!#"/&'&=4@2uBo  T25XzrDCBBEh:%0f#-+>;I@KM-/Q"g)0%HPIP{rQ9 @@ $&P{<8[;:XICC>.#-a)&%,"J&9%$<=DTI*'5oe71#.0(  ls +Ͱd/0ͰO/C33KͲF222t/mְ%Ͳ%m +@% +m% +@ms +%:+;2ZͲZ: +@ZM +u+6/'+ ;.?XV??;+VWVX+WVX #9>?;9<9=9>?X;<=VW........>?X<=VW.......@%m99:EFd$9ZRU99O0EPls$9KIJ999013!26=4&#!"6323276727#"327676767654./&'&'737#"'&'&'&54'&'&'@ <4"VRt8<@< -#=XYhW8+0$"+dTLx-'I&JKkmuw<=z% @@@ v '|N;!/!$8:IObV;C#V  &   ( mL.A:9 !./KLwPM$ /?O_o +ͱCs22/K{33#ͱS22,/[333ͱc22?>;5463!2&#"&5!"&5#".!#"264&"264&"@&  ?&&! 'ԖԖ@' ! LhLLh4LhLLh&@6/" && jjjj  hLLhLLhLLhLJ /Ͱ@/0Ͱ/K/ְ!Ͱ!-+CͰC=+3Ͱ3+ͱL+C-(*GH$9= 08 E$936999  H99@@ !%-36E$9014$ #"'676732>54.#"7>76'&54632#"&7>54&#"&aaok; -j=yhwi[+PM 3ѩk=J%62>Vca^ ]G"'9r~:`}Ch 0=Z٤W=#uY2BrUI1^Fk[|Lx /I3ͰA/1Ͱ/M/ְ"Ͱ".+DͰD>+4Ͱ4+ͱN+D.(+ HI$9>19F$94799A"&.47F$9015463!2#!67673254.#"67676'&54632#"&7>54&#"#"&www+U ,iXբW<"uW1AqSH1bd=Uco /ͰQ/CͰ`/YͰ)2,/p/ְ0ͰͰ0V+]Ͱ> NͰ]g+k2 ͱq+N># 3)9$9]V!CHQ$9g&+d$9CQ99`@ !5:3dfhi$9Y#0&jlno$9015463!2#!"&32>54.4>54&'37!"3274>32#".4632#".33535#5##www@w%3!##"&'&732>54.'&#"3267654.#"53533##5 YJ .H?MpJL1EF1@[Z@0HꟄ9%Fq}A:k[7'9C 5hoS6j+=Y4&P5"?j@*Q/iiQ.R*@)$1R6B@X?ZHsG;@"$ECPNZSzsS`0$/. 0$8].ggR4!9f:}R'!;ll/<W +Ͱ-/7ͱ22+ (08$9<7 !()$9015463!2#!"&2!463"&5!#4>2".673#!5##&&&&jjjj*M~~M**M~~MPM* r@&&&&Zjjjj|NN||NN|mP%``@  //+01463!2"'&&@4@&4&&4@@  //+014762#!"4&&4@4&@ /+ͱ+014762"'@4&&4@f4&&@ / +ͱ+015462"&&4@4&&@4@&:+3 Ͱ/3/ְͰ+Ͱ+ ͱ+015463!2#!"&73!!!265!^B@B^^BB^ ``  B^^B@B^^B  `@ 463!2"'4762#!"&&@4@4&4&&4@4@4&  //+01463!2"'&&@4@4&&4@@  //+014762#!"4&&4@4&:/ ;/<+015;2>76%67#!"&463!2+".'&$'.,9j9Gv33vG9H9+^B@B^SMA_bI\ A+=66=+A [">n 1&c*/11/*{'0B^^lNh^BO3@/$$/@*l +r%/Ͳ% +@%! + 22 /,/ ְͰ Ͱ++Ͱ2+!+ ͱ-+ 99+9!9% $901462+"&!3/!#>32!4&#"gdgTRdJI*Gg?QV?U JaaJIbb8!00 08iwE334>/ Ͳ  +  +)/ 5/%ְͱ6+)  12$9 99014766$32#"$'&6?6332>4.#"#!"&('kzz䜬m IwhQQhbF*@&@*eozz   _hQнQGB'(&(q4>7632&4762.547>32#".'632#"'&547"'#"'&(  &  \(  (  &  ~+54'k%%k'45%&+~(  (h  (\  &  h(  (~+%'45%l%%l$65+~  &  !3;CK]/ͰF2;/L/ְͰI+ ͱM+I@ #,48<@D$9%9;@  *.26>BJ$90146$ #!"'&264&"264&"676&'6.264&"264&"264&"LlL##KjKKjuKjKKj;P,2e2.e<^*KjKKjuKjKKjuKjKKjL;jKKjKujKKjK1M(PM+&97 #$9:3#*0$9014$ #"'#"&'5&6&>7>7&76?32$6&$ dFK1A  0) W.{+9E=ch'٫C58.H(YpJ2`[Q?l&싋%:dc+;ͲO+ /1Ͱ8/e/ְ&Ͱ&5+ͰC+Hͱf+&995 #;=a$9CEK99HNXY999;cKNa$9 991 #+$98*.CEH$90146$ #"'#"&'&4>7>7.76?32$64&$ 32$7>54''&'&'# E~EVZ|$2 $ |j`a#",5NK :(t}| $ 2$|ZV쉉X(  &%(HwR88T h̲hhZT\MKG{xH(%& (X|!>3!2%632#"'.7#"'&H  j '9 1b{(e US/*>33ʹ"26FJ$2I/43 Ͱ2 /3V/ְOͳJO+Ͱ/JͰOB+2;Ͱ26;B+GͰG/ 36Ͱ2;.+'ͳ"'.+3Ͱ3/"ͱW+0146;5463!5#"&5463!2+!232#!"&546;5!32#!"&546;5!32#!"&8(`L4`(88(@(88(`4L`(88((88(``(88((88(``(88((8 @(84L8(@(88((8L48((88(@(88((88(@(88((88;OY|D+NͲDN +D? +DI +4/$33Ͳ4 +4 +92@4 +,2P/TZ/<ְAͰAF+P2KͰV2[+A<09F%,MN$9K901476$32#"'.#"#"'.'."#"'.'.#"#"&46226562"&5462&"-U ! 1X:Dx+  +ww+  +xD:X1 &4&NdN!>!И&4&*,P  ..J< $$ 2#"&'"&547&547&547.'&7367>7654."$4632"&54&#"YYg-;</- ?.P^P.? -/<;-gD ) ) DEooE` 2cKl4 cqAAqcq1Ls26%%4.2,44,2.4%%62sL1qeO , , OeH|O--O|+ L4  .24V/ Ͳ +@ +  +@  +2/Ͳ2 +@2- +2 +@$ +5/6+ 92()990147632!2#!#"'&5463!54632#"&=!"& @  `    ` ?    @     @ -    5p+!Ͳ! +@! +./6/ְ1Ͱ Ͱ1%+Ͱ* ͱ7+19* !99 99.!$9 901467&5432632#!"27654&+4&+"#"v,Ԝ;G_j) `  _   7 ,>jL>цY _ `  5+Ͱ)2+$Ͳ+ Ͱ2/6/ְͲ +@ +-+Ͳ- +@ +7+- 99 99$992$9  901467&5432632#!";;26532654'&"v,Ԝ;G_j)    7 ,>jL>ц  `  ` PX`+%533NͰX/TͰ`/\a/ְ Ͱ R+VͰV*+1Ͱ1^ ZͰZ/^Ͱ^3 (Ͱ(/3Ͱ18+Jͱb+R 99V $9^Z#.TW$91*>AD$93(-98@9X#(38$9T!*1:J $9`@  .>@-$9\D$90154>72654&'547 7"2654'54622654'54&'46.'#!"&$462"6  %:hD:FppG9Fj 8P8 LhL 8P8 E; Dh:% yy&4&&4>ƒD~s[4Dd=PppP=d>hh>@jY*(88(*Y4LL4Y*(88(*YDw" A4*[s~Dy4&&4&>EM.+@ͰC/*3ͰM/7Ͱ/3 Ͱ2N/ְͰ ͰB++Ͱ++'Ͳ' + +'4+GͰG0 +=Ͱ=K +9ͱO+  99+-@9994'.?99G69M14932#"' 65#"&4632632 65.5462 $=.$264&"& <#5KK5!!5KK5#< &ܤ9GppG9&4&&4&$KjKnjjKjK$&jjb>PppP>buោ4&&4& %W/ 33ͳ $2/&/ְͰ +ͳ  +ͳ +Ͱ/Ͱ+"ͱ'+01546;#"&35463!23!5!32#\@@\8(@(8`@\\`@\(88(\\!-j/%./ְ"Ͳ" +@ +"'+Ͳ' +@ + '+Ͱ/ ͱ/+"+99' %($9  9990156467&5462#!"&5!"&324#"&54"8P8¾L4@Ԗ@4LgI;U (88(¥'4LjjLLIg U;@"?/Ͱ/ ͳ +Ͱ "#/ְͱ$+9"99015!#!"&463!2+#!"&3264&+jj&@\@\@PppP@j& \Ͱ>/D+01462265462265462+"&5.463!2+"&5#"&&4&&4&&4&&4&&4&G9L44L9G&L44L @&&`&&&&`&&&&=d4LL4 d &4LL4,<LSq/Ͱ*/!Ͱ:/1ͰJ/AͰ/MͰ/T/ְͰ+MͰM+ ͱU+-.=>$9M%&56EFN$9MS901463!2#!"&7!!"&5!5463!2#!"&5463!2#!"&5463!2#!"&!&'&'8((`8(8((8`(8@@@x @(8(`((88H8( @@@@@@n 9 -=M]m} -=463!2#!"&7!5463!2!!546;2+"&546;2+"&546;2+"&546;2+"&546;2+"&546;2+"&546;2+"&546;2+"&546;2+"&546;2+"&546;2+"&546;2+"&546;2+"&546;2+"&546;2+"&546;2+"&546;2+"&546;2+"&&&&& @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @ &&&&Z   @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  1AQaq463!463!2!2#!"&7!5463!2!!#!"&=!546;2+"&546;2+"&546;2+"&546;2+"&546;2+"&;26=3;2654&+"#54&+"546;2+"&546;2+"&546;2+"&546;2+"&546;2+"&&@8((8@&&& @ 8(@(8 @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @ & (88(&&&Z   (88( @  @  @  @  @  @ @  @  @  @   ``  @  ``  @@  @  @  @  @  @  @  @  @  @ @&/7[c3+^3"Ͱ2%/33Ͱ7/b3(Ͱ*/ ͰX/M3ͰSd/ְ'Ͳ' +@ +'$ +1Ͱ1(+ 422=ͰV2Ͱ8Ͱ= +]Ͱ]D+N2ͳaD+ͰIͰI/e+(1!"*999D]^c999a9%314]`$905\a$9(@A99*;;463!2+"&5!"&5#"!#264&";;26=326=4&+54&+"#"264&"@&@&&&ԖԖKjKKjKjKKj4&@@&&&jjjj jKKjK jKKjK ;?I /@33Ͱ%2 Ͱ3/<ͳ A$2?/J/ְͰ +Ͱ62ͳ< + Ͱ /<Ͱ$+.2ͳ=$+Ͱ)Ͱ)/@+FͱK+01546;#"&35463!23;;26=326=4&+54&+"#"!5!32#\ \`8(@(8` \\`@\(88(  \\:f.+/Ͱ%2!/Ͱ2  ͳ!+Ͱ /3;/<+2/#367$9 99!89999 901575#5#5733#5;2+31 #32+53##'53535 `@@`&&E%@`@E&&`@@`    @ :# @ @   @B + /Ͱ/Ͳ +@ +/ְͱ+ 9999017!7!!57#"&5;!@   @K5 @5K3G /ͰͰ2+/Ͱ0Ͱ%24/ְͰ++2Ͱ)2!+ ͱ5+015463!2#!"&%;265!;2654&+"!4&+"www@w&&&&&&&&ww@w&&@&&&&@&&3I /Ͱ2Ͱ0/%3Ͱ+4/ְͰ.2Ͱ+&2 Ͱ !Ͱ!/5+015463!2#!"&3!;265!26=4&#!4&+"!"www@w&@&&@&&&&&ww@w&&&@&&@&&&-M3)4762 "'$4762 "'-   2 w 2  .v   2 w 2  .3  2  ww  2    2  ww  2  M3)647 &4?62"/$47 &4?62"/ w 2   .  2v w 2   .  2   2 .  . 2    2 .  . 2M3S)64762"' "/4762"' "/M    2  ww  2    2  ww  2  .  2 w 2  .  2 w 2M3s)4?62 62"'4?62 62"'M 2    2 .  . 2    2 .  . 2 w 2  .  2 w 2  . -Ms3/+Ͱ2+ 9014762 "'-   2 w 2  .3  2  ww  2  MS3/+2ͱ+901647 &4?62"/ w 2   .  2   2 .  . 2M 3S /3/+ 9014762"' "/M    2  ww  2S  .  2 w 2M-3s/Ͱ 2/+9014?62 62"'M 2    2 .  . 2 w 2  . />/ 3#Ͱ#Ͱ,/0/ְ Ͱ '+ ͱ1+'  $901463!2#!#!"&54>5!"&3!2654&#!"^B@B^^B && B^ @   @B^^BB^%Q= &&. aa^(a^(!Cb+@3Ͱ82/03Ͱ(2D/ְͰͲ +@ +"+=Ͱ5Ͳ5" +@5- +E+ 9=5,90154>;2+";2#!"&%4>;2+";2#!"&Qh@&&@j8(PppPPpQh@&&@j8(PppPPphQ&&j (8pPPppPhQ&&j (8pPPpp!Cn+03Ͱ82/@3Ͱ&2D/ְ Ͱ Ͱ/ +@ + "++Ͱ+<Ͱ^^^gggxTTxTpppjKKjK\BB\BB//B/hP88P8  /Ͱ /ְͰͱ +01$  $aa^a^,A&/Ͳ& +& +@&* +& +@ +-/ְͰ ͱ.+&990147623 #"&5465654.+"'4&ɢ5  #>bqb&4f4&mǦ"  #D7euU6 &&@LX.+ͰK/V3EͰP2>/73Ͱ2;  Y/ְ'Ͱ'B+HͰHN+TͰT4+ͱZ+HB> 99N9< $9T7 99EK4'$9 ; $90147&5472632>3#".'&7;2>54&#""'&#"4>2"&$4>2"&3lkik3=&\Nj!>@bRRb@v)GG+v=T==T=g=T==T=RXtfOT# RNftWQ|Mp<# )>dA{ XK--KXx PTDDTPTDDTPTDDTPTDD,V+Ͱ!/ Ͱ)/-/ְͰ%+ Ͱ +ͱ.+ %!9 9 !$9)%9015463!2!2#!"&73!2654&#!"&=4&#!"\@\\\@\8((88(@(88((8\\ \@\\(88((88(@(88(u3Ey+6Ͱ@/"Ͱ2(/ Ͱ0/F/ְͰ,+ Ͱ #+Ͱ=+ͱG+,49 (9#'9@699 (+90,9015463!2!232#!"&7>3!54&#!"&=4&#!"3!267654#!"\@\ \6Z.+C\,D8((88((8+5@(\&5([\\ \1. $>:5E;5E(88(@(88(#,k#+ #8@+ Ͱ7/-Ͱ#/?3Ͱ;2/A/ְ Ͱ +!Ͱ!:+>Ͱ>+ͱB+! %+$9:,-67$9> /3$9#- (1$9 $901$  $ >. 462"&676267>"&462"aa^NfffKjKKj9/02%KjKKja^ffffjKKjK/PccP/yjKKjK #8@+ Ͱ1/'Ͱ#/?3Ͱ;2/A/ְ Ͱ +!Ͱ!:+>Ͱ>+ͱB+! 83$9:&'01$9> /*$91,5$9' 99# $901$  $ >. 462">2&'."'.462"aa^NfffKjKKj9%%20/KjKKja^ffffjKKjK3yy/PccP/1jKKjK '/7+ Ͱ&/Ͱ//63+Ͱ22/8/ְ Ͱ )+2-Ͱ-1+5Ͱ"25+ͱ9+-) $951 $9& $9+/ $901$  $ >. 463!2#!"462"$462"aa^Nfff&&&&KjKKjKjKKja^ffff4&&4&jKKjKKjKKjK3;C] +37Ͳ +Ͱ;/ͰCͰ+D/ְͰA+ͱE+A !48<$9C  %&/>$9013!2#"'##";;26=326=4&+54&+"#"264&"6264&",,ܒlKjKKjKjKKj,,XԀjKKjKjKKjK+7CO[gs +Ͱ/A33ͱ;22*/Yq$3#ͳSk$26/Me}$3/ʹG_w$2//ְͰ+ ,22Ͱ22'ͰD+82KͰKP +WͰW\ +cͰch +oͰot +{Ͱ{ +Ͱ +Ͱ>2+2Ͱ2 +@ ++ ͱ+015463!2#!"&7!!54;2+"54;2+"54;2+"543!2#!"54;2+"54;2+"54;2+"54;2+"54;2+"54;2+"54;2+"54;54;2+"54;2+"K55KK55K```````````````````p```5KK55KK5`````````````````````````@?V0/JͲ0J +@0< +7/BͰO/!ͰT/W/ְ Ͱ Ͱ +@Ͱ@L+*ͱX+@:9L!07$9*%.99B7@HL999!OMRV99901462+"&5.47>32327676#"/.#"#"'&7632327#"'.#"@KjK#@##WIpp&3z # ڗXF@Fp:f_ 7ac77,9xR?d^5KK5#::c#+=&>7p #'t#!X: q%\h[ 17@?EKjr0/UͲ0U +@0< +7/LͳCL7+HͰp/!ͰI/s/ְ Ͱ Ͱ +@ͰF2@W+m2*ͱt+@:9W!07BHLk$9*%.99L7@SWXZ$9HF[ejklm$9ph9!JKnr$901462+"&5.47>32327676#"/.#"#"'&76755675323275'5&'. #"75#"'@KjK#@##WIpp&3z # ڗXF@Fp:f_ ͳשfk*1x8 2.,#,쩉-!5KK5#::c#+=&>7p #'t#!X: `eov:5 \t-  |*[ 3$"+%/&+"9901647 &4?62"/5463!2#!"& w 2   .  2i@   2 .  . 2i@@-S$94762 "' >/.$47 &4?62"/-   2 w 2  .u >  > I w 2   .  23  2  ww  2      2 .  . 2;K< 1Bi7I))9I7 !% %!bcB/4 <B&67632#"'.5!"   ( ,( )##@258++ 36Ͱ2+6 +@+& +0/43Ͱ20 +@ +29/.ְ23Ͱ 2.3 +@. +3)+72"Ͱ2") +@" +2:+)34699"9063899901546;546;2!76232++"&=!"&5#"& !!S  S-S  `SS3;CK7+2Ͳ3+0+K/ͰC/ L/ְ25Ͱ<25 +,Ͱ2,9 +@2/Ͱ 2/+EͰE +$Ͱ$I +!ͱM+,5 12$9/)9(999$E99K7@ !:=>@F$9 5.5462"&6264&"264&"264&"4,,4pp4,6d7AL*',4pp4,DS,4pp`8P88P88P88PH8P88P@4Y4Y4PppP4Y%*EY4PppxP88P8HP88P8P88P8 '6B]iw4+Y GͰ /Ͱ/{Ͱ// ְͰ7+>Ͱ>^+eͰeK+Tͱ+7@ "#,/0$9^>CD$9KeNOYjkuxy$9 4,:;CDKT$9"#NO$9{ ghku$901463!2#!"4?632&#"&'&4762#"'462"&7?654'7#"'&462"&4762"'463!2#!"@USxySN('#Tp   YR#PTUSxyS    7@xSSU#'(PVI   i@'(VvxSSUOW@?   `,<T:+1Ͱ#/Ͳ# +#) +=/-ְ26Ͱ2 6-+ ͱ>+6-#99 9#1 9901&7!2+"&=467>54&#"#"/546;2+"&c0PR'G,')7N;2]=A+#H    >hS6^;<T%-S#:/*@Z}g.H+Ͱ2/Ͱ,/#//ְ2Ͱ'2 +@ + +@ + 20+01=46;#"&=463!232#!"&5463!2#!"&&@@&&&@&&&&&&&@&&&&&&&Z&&&&b2+ /ְͰͳ+Ͱ/3Ͱ2!+01&63!2#!"&'5463!2#!"&b%@%''&&&&@&&&&&&&&k"G+3Ͱ2/3Ͱ2@+EͰEBͰ-/6H/*ְ9ͰC2*9 +@*# +E29AͰA/I+E $9@#9>9-(1999901353#5!36?!#3#/&'#4>54&#"'67632353!'&Ź}m 4NZN4;)3.i%Sin1KXL7~#& *ا* @jC?.>!&1' \%Awc8^;:+54&#"'67632353!'&Ź}m 4NZN4;)3.i%PlnEcdJ~#& *ا* @jC?.>!&1' \%AwcBiC:D'P-+/+01&6763!2#!"&'7!! &:&? &:&?uPmK,)""K,)"5hH+_37/1ͳ,17+<i/ְVͲV +@V[ +V +ͳ +ͳK+BͰ!2P +>Ͱ(2j+S99> FH$9B&97H>NY[$9<PV99,4S99011327654.54632326732>32#".#""#"&54>54&#"#"'./"'"%_P%.%vUPl#)#T=@/#,-91P+R[YO)I-D%n  "h.=T#)#lQTv%.%P_ % #,-91P+R[YO)I-D%95%_P%.%vTQl#)#|'' 59%D-I)OY[R+P19-,#'3#+3Ͱ%/3 Ͱ2/,4/ְͰ(+/ͳ/(+$Ͱ$/Ͳ$ +@ +$ +@$! +/ +ͱ5+/( 99 ,199,2 $9015462 =462!2#!"&463!5&%46  &&4&r&4&&&&&&&&&&4&&4&G s7CK.+"3)L/8ְ?Ͱ?/+"Ͳ"/ +@"& +/" +@/, +"+ͱM+?84B99/2ADE$9"H999 K9999.)45990164762#"'32=462!2#!"&463!5&'"/5462&%4632   R 76`al&4&&&&&}n  Ri&4&e*f"3  R  `3&&&4&&4& D R&&57&5462!467%632#"'%.5!#!"&54675#"#"'264&"  8Ai8^^.    @ o&&}c ;pG=( ]&4&&42 KAE*,B^^B! `  ` fs&& jo/;J!#4&&4&$ %-(-/ ./+ְ ͱ/+ + 9 - 90167%676$!2#"/&7#"/&264&"$ {`PTQr @ U @8P88PrQ P`  @U @P88P8+ $3/33/ְͰ+Ͱ + ͱ+6>+ >+ >+     ... ......@9011!2!6'&+!!̙e;<* 8GQIIc@8 !GG + /Ͱ/!/ְ ͱ"+$901$  $2?64' 64/&"aa^4f3f4:a^L4:f4334f: + /Ͱ/!/ְͱ"+$901$  ,2764'&" aa^,f4:4f3a^4f4f4 //!/ְ Ͱ +ͱ"+  $901$  $27 2?64'&"aa^,f4334f:4:a^4f3f4: / /!/ְ Ͱ +ͱ"+  $901$  $2764/&" &"aa^,4f44fa^4:4f3f@ /Ͱ/3Ͱ2/3Ͱ2/+6?d+ . ?$+ . +  +++ ....@  ............@01!%!/#35%!'!7†/d jg2|bx55dc  @h/3Ͱ 2 / 3 Ͱ 2/+6>j+ .  +  +.. ......@017!%!!7!!  G)DH:&H;KdS))MUJ+?3 +.+/,3Ͱ$2U/V/ ְ2.Ͱ#2O. +Ͱ/OͲO +@ +S. + Ͳ S +@ ) +W+ E9O9.S9 D9J6BG$9U P999011463!2#"&=46;5.546232+>7'&763!2#"/ $'#"'&264&"`dC&&:FԖF:&&Cd` ]wq4qw] @&4&&4`d[}&&"uFjjFu"&&y}[d ]] 04&&4&#`!+Ͱ2/ Ͳ +@ +$/ְͲ +@ + +@ ++ ͱ%+ 99 901546;4 +"&54&"!2#!"&8( r&@&Ԗ(88(@(8`@(8@&&jj8((88 #+3+ Ͱ#/'Ͱ3//Ͱ+/Ͱ/4/ְ Ͱ +%Ͱ%-+1Ͱ1)+!Ͱ!+ͱ5+1-@ "#&'*+$9/3@  !$%() $901$  $ >.    6& 462"aa^Nfff,,X>aԖa^ffff,X>ԖԖ/9 /,33ͱ$220/ְ Ͱ +Ͱ +)ͱ1+01546;2+"&%546;2+"&%546;2+"&8((88((88((88((88((88((8`(88((88((88((88((88((88/3 +Ͱ/Ͱ-/$0/ֱ 22 ͱ(22 ͱ1+01=46;2+"&546;2+"&546;2+"&8((88((88((88((88((88((8`(88((88((88((88((88((88+EJ /!ͱ622A/F/ְͱ,22;+ ͱG+;$4999A!).999015463!2#!"&264&"';26'&'&;276'&.$'&www@wKjKKjK    \ f ww@w jKKjK  ܚ H     f  / //ְ Ͱ +ͱ+  $901$  $%32764'&aa^2  ! a^% @J@%65+/0/%ְͱ1+% 901476227"/64&"'62764'&" 6%%k%}8p8~%%u%k%~8p8}j6j6[<<k%%%}8p8}%k%t%%~8p8~4j4j-<( /Ͱ/ /ְͰ+ ͱ!+015463!2#!"&3!26=4&#!"www@w&&&&ww@w&&&&/: +Ͱ-/$Ͱ/0/ְͰ+ ͱ1+ (9901463!2#!"&73!2654&#!"5463!2#!"&w@www^B@B^^BB^@ @wwwwB^^B@B^^B@@@/+Ͳ +@ +/ְͱ+99017&?63!#"'&762+#!" @(@>@(@ %% $%-/Ͳ +@ +/ְͱ+ 990163!232"'&76;!"/&  ($>( J &% $( /Ͱ/%/ְͰ+ͱ&+015463!2#!"&2764/&"'&"www@wf4ff4-4fww@wq4f4f-f%/F /Ͱ./0/ְͰ*+ͱ1+*"&$9.% '$9015463!2#!"&%! 57#57&76 764/&"www@w  `448.# e \Pww@wW  `844` #  \P)( /Ͱ#/*/ְͰ+ ͱ++015463!2#!"&27327654&#!"www@wf4 '& *ww@w14f*&')5C /Ͳ +@ +./6/ְͰ'+ͱ7+."'99*9015463!2#!"&3276'7>332764'&"www@w ,j.( `'(wƒa8! ww@w  bw4/*`4`*'?_`ze g /Ͱ//ְ Ͱ +Ͳ +@ ++ͱ + $9 $9$901$  $ >. -aa^(a^(1-< /Ͱ/./ְͰ+ ͱ/+-&99")99015463!2#!"&%3!2654&#!"63!2"'&www@w   @ ((Bww@ww    ###@-< /Ͱ/./ְͰ+ ͱ/+!(99$+99015463!2#!"&%3!2654&#!"&762#!"www@w   @ @B@((ww@ww    C#@##-< /Ͱ/./ְͰ+ ͱ/+ '99$+99015463!2#!"&%3!2654&#!"476'&www@w@##@##ww@ww(B`BZ+@Ͱ^/<3Ͱ32/03Ͱ(2%/a/b+^@I9%901546;&7#"&=46;632/.#"!2#!!2#!32>?6#"'#"& BCbCaf\ + ~2   }0$ #  !"'?_ q 90r p r%D p u ?|=+Ͱ/2= +@4 +/-3Ͱ%2!/@/ְ2/Ͱ$2/ +@/* +/ +@ +/0+8ͱA+0/99899!9901=46;#"&=46;54632'.#"!2#!!546;2#!"& a__ g *`-Uh1  D  ߫}   $^L   4b|W/ Ͱ=/%c/ְ@Ͱ@Z+!2SͰ)2S+Oͱd+@9Z9S =G999H9O1899 WR[99=46O$9%!*9901?676032654.'.5467546;2'.#"+"&=.'&4g q%%Q{%P46'-N/B).ĝ 9kC< Q 7>W*_x*%K./58`7E%ǟ B{PD  cVO2")#,)9;J) "!* #VD,'#/&>AX2 ,-3>)9+ /.3Ͱ&2/Ͱ$?/@+01546;267!"&=463!&+"&=463!2+32++"''& pU9ӑ @/Ԫ$  ] VRfq f=Sf o E[.+3/(3:Ͱ 2=/3DͰ2F/1ְ;2*Ͱ2*1 +@* +$21* +@1@ +62G+*1 9901&76;2>76;232#!!2#!+"&5!"&=463!5!"&=46;  % )   "       PW&WX hU g Jg Uh 08l)+./#3Ͱ2/3Ͱ128/9/,ֱ22%ͱ122%, +@% +,% +@, + 2%5+ͱ:+89901546;5#"&=46;463!2#!!2#!+"&=#"&!264&#! @jjv u~v||PT]aen^I+@3N/nDEMU]f=$3ͷd4RS^_c$2/e3QT`ab$3ͳ!*$2 +@ +$22o/p+6+ L V=+ T.\a FD+ `.Cb i=+ k"> )L+L+L+V+k!k"+>*>)+3>)+4>)+=>)+`D`C+FEFa+ML+QV+RV+\S\T+UV+\]\T+F^Fa+`_`C+bcbi+kdk"+ek"+bfbi+3^+ gbi+hbi+=+ klk"+mk"+nk"+gbi #9h9lk" #9m9@")>CFLV\gmhikl................@,!")*34=>CDEFLMQRSTUV\]^_`abcdefgmnhikl............................................@NIYj9901546;'#"&=46;&76;2!6;2!6;232+32++"'#+"&'#"&%3746573'#!37465!mY Zga~bm] [o"դѧ u #KQ#F"!QN@@X hh @@h h+,83H\+(+33Ͱ42 +@/ +)2G/KͰ /\3 Ͳ222 +@  +2]/ְ24Ͳ-I2224/Ͱ//34*+2)Ͱ2^+/9*47FKZ$9)E9GD9K999 Y901373273&#&+527536353#5"'#"&#%22>54."#52>54.#8o2 Lo@!R(Ozh=ut 3NtRP*H :&D1A.1,GHI$9F:9997D $98.:990176;46;232#"'&5333!53'#36?5"#+#5!76;53!3/&5#" iFFK//Kq   x7  y˱H l` @jjjjjZ sY wh/" "})GR%+HͰ)/ 33ͳ"&$2*/CͰ@2EͰ6/9Ͱ298S/ְ Ͱ 8+*27Ͱ&287 +@8) +7D+#2GͲGD +@G +T+6<$+ &R &%&R+R..%R....@ 989D7!'(/?HI$9G;:99H%9* M$9C+?990176;46;232#"'&333!53'#3!56?5"#+#5!76;533/&5#" iFFK//KYq   x7  yH l` @jjjjZ sY wh/" ")9IYu+&Ͱ27/.ͰG/>ͰW/NͰ2Z/ְ Ͱ J+*:222SͲSJ +@S" +@S3 +@SC +[+ 9J97 $90176;46;232#"'&463!2#!"&55463!2#!"&5463!2#!"&5463!2#!"&" f@@l` @y")9IYu+&Ͱ27/.ͰG/>ͰW/NͰ2Z/ְ Ͱ )+*:J222"Ͳ") +@"3 +@"C +@"S +[+ 9)97 $90176;46;232#"'&463!2#!"&55463!2#!"&5463!2#!"&5463!2#!"&" f@@l` @y"8KV&/3/Ͱ6/Oͱ 22U/Ͱ?/@Ͱ<2@? +@@ +:2W/ְ Ͱ +MͰMA+<Ͳ +A< +@A? +<R+ ͱX+ 9M*+9K$9A&/G999<6:OU$9R32996/+9O299U 990176;46;232#"'&%4632#"'&'73267##"&733!5346=#32654&#"" m{8PuE>.'%&TeQ,j{+>ID2FX;4l` @i>wmR1q uWrrr :MrL6)?j"8KV?/3@Ͱ<2@? +@@: +&//Ͱ6/OͰU/Ͱ2W/ְ Ͱ +MͰMA+<Ͳ +A< +@A? +<R+ ͱX+ 9M*+9K$9A&/G999<6:OU$9R3299&@ $9/*96+9O29U 990176;46;232#"'&4632#"'&'73267##"&733!5346=#32654&#"" m{8PuE>.'%&TeQ,j{+>ID2FX;4l` @i>wmR1q uWrrr :MrL6)?j@\8 +Z3Ͳ +@ +@/ +]/ְͰ+ ͱ^+015463!2#!"&732654&#"467>767>7>7632!2+".'&'.& &&&%&&%`$h1D!  .I/! Nr7.' :@$LBWM{#&@&&&&%%&&%r@W!<%*',<2(<&L,"rNV?, L=8=9%pEL+%@\0/ Ͱ 2 +@K +]/ְͰ+ͱ^+013!2654&#!"4632#"&46767>;#!#"'.'.'&'.'.& &&&%&&%`&#{MWBL$@: '.7qN !/I.  !D1h$&&&&%%&&%+LEp%9=8=L ,=XNr%(M&<(2<,'*%<!W@r% *2?Sem+ ͰP/0Ln|$3Gͱ22GP +@G +/Ͱ/3sͲAJ222+/.3,Ͱo2$/9ͲX222/a33Ͱ3Ͱ<2/ְͰ9Ͱ1+0Ͳ01 +@0. +10 +@1+ +0@+CͰ; TͰCM+I2LͳfLM+kͰL\+ͳ\+nͰn/ͱp22+Ͱ2x+Ͱ/xͰ+Ͱ2+2Ͱ2+ Ͱ Ͱ/+93?99@0>99C=P99T;$9015463!2#!"& 7>7654'.'&! 753##35#'33273#5#"'&3276=4'&#"542"3632#"'532=4#"3273##"'&5#54762#32746453#"'&7354"www@w A+&+A  B+,A RPJ # JZK35DBCC'%! p3113C@@EC $)  )#!2 $)CCCf"D 54BBBww@wET+<<+TS,;;,W FFY\g7("(-:&&<:&&:443(*54*)$H12%-(rU;&&:LA3  (&"33 !-AS[mw4+^3/ʹ25\`$2/Ͱͱ;v22/Ͱq2!/l3Ͱ/P3ͰU2Z/Gͱy22/ְ.Ͱ.( )Ͱ)/(Ͱ.?+9Ͱ429& %Ͱ%/&ͳB9?+TͰ96+\ͳW\6+LͰ\x+{ͳt{x+nͰn/]k33tͰ{+2ͳ+dͰd/Ͱ +2Ͱ2+2 ͱ+66R+ ",#$"#$,...."#$,....@() $9&%2;99\6GP99{xi`999d999999n99 o999!@ 78@Aik$9)($9Z'990147>76  '.'&3335!33#&'&3273##"'&5#547632#"'&72=4"353276=4'&#"5#632#"33273#5#"'&327676=##"=354'&#"542X;:Y X::Y oidkȀjGDfyd/% .06YYY&CE%%EC&ZVV^Y-06 62+YY''.[[[52. 'EH$[!.'CD'YZt;PP;pt;PP;p9^qJg1%=6* lRP%33%PQ%33&?FFEE077II86-CC!+} 7>%O%35 1 3 $EWgO%33%O.DD.{'&72'&76;2+%66;2+"'  ( &' P *o"-J. -Z-#7,(+ Ͱ/Ͱ58/9+($/999015463!2#!"&;274'&+"%;276'56'&+"www@w~}   ww@wc $`" j!#  #/$+$0/ְ ͱ1+ 99014>7>76  '.'.32764'&jGGkjG~Gk~!"! lAIddIAllAIddIAt& @J@&@ / ֲ222Ͱ2!+01 5577'5 @RVVWRW.\?il``l1~~ # + Ͱ /Ͳ +@ +2//3/#/!/$/ְͰ++++ + ͱ"+%+6&....ɰ6&....ɰ6&! . !.#"."#.ɰ6@ $99999#99013!3!'75%77777yx#C j''MaM}|yjC#A$VUG%/? /Ͱ/)Ͱ/$34Ͱ./Ͱ<@/ְͰ"+'Ͱ',+Ͱ+72 ͱA+'"$9,0?9999)"'+$94&,99015463!2#!"&73!265##"547#$3264&#"%;26=4&+"tQvQttQQt#-$܂"((((EvQttQQttz##?D~|D? =(())8 /Ͱ2/3 /ְͰ+Ͱ+ ͱ!+015463!2#!"&264&"264&"www@w||||||ww@w||||||| //+$901$  $37!3aa^g^h h^5a^2-2P#<P\g<5/(Ͱf/ah/cֱi+(5/;99f$&)-STe$9a 9901>767$%&'.'.? 7&'.'&7>7.'$7>'.676'&"8$}{)<U,+!  #7 ,$Vg.GR@&\74~&p )4 2{ "8 eCI0/"5#`# ## /1 "[\kr,y9R ;&?L .AU`iGT/O3EͰH2j/VְbͰb9+ ͱk+9b=>L]ef$9 $;99ETL9015463!2#!"&7>776'&'&7>746&' '>76'.&676&66'4&www@w$ i0 +p^&+3y/" h . ."!$2C',,&C7-F XjM+'TR$ww@wD$4" P[ & 57!? "0>8Q.cAj'jj#"p1XRMBn \i6-+.N#b/Ͱ /3 Ͳ +@  +$/"ְ Ͱ2 " +@ +" +@" + Ͱ/%+9 9 90156767673!!327#"'&'&'&5N[@@''l '2CusfLM`iQN<: 67MNv|v$%L02366k3\ /Ͱ!/(Ͱ2-/4/ְͰ'++2 ͱ5+399'-9 )999!9(9015463!2#!"&3327675#"'&'&5!5!#www@w*+=>NC>9MXV3%  10Dww@wlN+*$% $8c'#Z99*(@/ְ ͱ+ 90176;46;232#"'&    & /ְͱ+901&7632++"&5#  ^  c  &  @//+901476!2#!'&@  & } b  ^ //+ 9015463!546'&=!"&&      q&8M/Ͳ +@# +2 +@ + 29/ְͱ:+ '1$99990147632327632#"'&#"#"6767qpHih"-bfGw^44O#AY'T1[VA=QQ3KJ?66%z䒐""A$@C3^q|}} !"lk) =KK?6  (/ְ2Ͱ2+ 2 Ͱ2+01!%!%VKu-u5^mf}~ "=EM["/ͰAͰH2\/ְͰ#+ 2&Ͱ"29&#+3ͳ+&#+0Ͱ0/+Ͱ&N+Vͱ]+&#>BFJ$93999+099ADL$9014632"&467'&766276!+"&=##"&5'#"&264&"264&"4632#"&<+*<;V7>5'&7>.'&'&'&7>7>767&'&67636'.'&67>7>.'.67'.'&#"'.'.6'.7>7676>76&6763>4'>&4.'.'.'.'.'&6&'.'.6767645.'#.'6&'&7676"&'&627>76'&7>'&'&'&'&76767><&'&23256&'&4723#76&7?4.6>762674.'&#6'.'. "  V5 3"  ""#dA++ y0D- %&n 4P'A5j$9E#"c7Y 6" & 8Z(;=I50 ' !!%&&_f& ",VL,G$3@@$+1$.( *.'  .x,  $CN7  J#!W! '  " ';%  k )"    '   /7*   I ,6 *&"!   O6* O /     Wh   w*   sW 0%$  ""I! *  D  ,4A'4J" .0f6D4pZ{+*D_wqi;W1G("% %T7F}AG!1#%  JG 3   J  <   mAe  .(;1.D 4H&.Ct iY%  "+0n?t(-z.'< >R$A"24B@( ~ 9B9, *$        < > ?0D9f?  .Y  G   u7   $37C[bu'+ Ͱ/ͰB/c/ְ Ͱ S+ͱd+S @  %)468@D\a$9'+Sb^$9FIN$9B"46:DU$901$  $>?>7&'!7 %&'327&#63"3>7&#">2&'>7&aa^^XP2{&% .0x||*b6~#sEzG<L $MFD<5+  CK}W)oa^2|YY^D 1>]yPեA4MWME6< 5* @9IK<^/#Ͳ# +@ +D/ͲD +@ +_/ְIͰ 2IͰ/I +@IS +I(+Ͱ Ͳ( +@(5 +`+I9(@$9 9#9D $99014632632#"'#"$&547&32>54./.543232654.#"#".#"ែhMIoPែhMIoPxIoB':XM1h*+D($,/9p`DoC&JV*x& i55K55q*)y(;:*h )k5555K*x?x*& /8 /#ͰͰ/+30/ְͰ+ Ͱ '+ ͱ1+01463!2#!"&3!2654&#!"3!2654&#!"&&&&  @&&&&19L9/5:/"ְ*2Ͱ2" +@ +" +@"' +"3 7ͱ;+"4589$9014763!2#"'#++"&5#"&5475##"&462"IggI8(3- &B..B& -3(8kk(8+Ue&.BB.&+8뺃%-~ /3Ͳ  + $ + 22@  +2-/)./ְ!Ͱ!+Ͱ' +Ͱ+Ͱ+ ͱ/+(-99+'99),9901463!2"&5#"&5#"&5#"&462"pPPp8P8@B\B@B\B@8P8 PppP`(88(`p.BB.0.BB.(88+ !"/ְͰͱ#+ 9901$  $ >&'&#"'.aa^]^/(V=$<;$=V).a^J'J`"((",9I&?'&767%476762%6'%"/'&5%&2>4.", $ $ " $ $  ܴ  [՛[[՛k `2 ^ ^ ` ` ^ ^ 2`՛[[՛[[1:$+Ͱ)/2/ְͰ-+ ͱ3+ -/9)'90146$763276#"$&732$7#"$547s,!V[vn)^zf킐[68ʴh}))Ns3(zf{n 6<@+&/Ͱ*Ͱ /,/-+*#901463!2#!"&463!2#!"&3!264&#!"@&&&&@&&&&@&&&@&&&&&&@&&44&&4& `BH/+,3 +A/3Ͱ2./ Ͳ . +@ +2C/FI/@ְ2.Ͳ@. +@@ +@@ +.-+Ͱ2- +@ +@ +J+.@ 5>CE$9- &FH$9 /&5>$9C99F990146;'&462!76232+"/##"./#"'.?&5#"46  &&4L4&&&C6@Bb03eI;: &4&&4&&4&4&w4) '' 5r}G(/ְ1Ͱs21 +@ ++1z9014?63%27>'./&'&7676>767>?>%63#&/.#./.'* 46+(  < 5R5"*>%"/ +[>hy  @ 5d)(=Z& VE/#E+)AC (K%3?JUkc"/*Ͱ1/Ͱ}/oͰj/Y/dְ_ͱ+_de91*@ >8BNTa$9 0dev{$9o}|9jp9901476$6?62 $.776$'.$&7>'&676&'&7676&'&&676.76&'.&676'.76&&YJA-.-- 9\DJՂ % Q//jo_--oKDQ#"N  {WW3' 26$>>WCw%`F`F_]\df`$E ""F!I  B8/Ka`s2RDE5) %^{8+?` r 2/ְͰ+ͱ+ 9 999014$7&>7#"&$̵"#ÊI$~EacxWW^ czk8j/Ͱb/[Ͱ l/,ְ@ͱm+@,S9[ U]g$9014636$7.'>67.'>65.67>&/>./"+f$H^XbVS!rȇr?5GD_RV@-FbV=3! G84&3Im<$/6X_D'=NUTL;2KPwtB X^hc^O<q&ռ ,J~S/#NL,8JsF);??1zIEJpqDIPZXSF6[?5:NR=;.&15Pt=   ' /3Ͱ /Ͱ/Ͱ// +0175!+!"&5!!5463!2sQ9Qs**sQNQsBBUw wHHCTwwTC 1s /Ͱ//Ͳ/ +@/* +/ +@! +/2/ְ Ͱ +ͱ3+  %$9/ $9%&99 $901$  $ >. 5463!54632#"&=!"&aa^( ` ?   a^(     1s /Ͱ*/!Ͳ*! +@*. +!* +@! +/2/ְ Ͱ +ͱ3+  %$9* $9!99 $901$  $ >. 47632!2#!#"'aa^( @  `   a^(d @    ?/< /Ͱ/0/ְͰ+ ͱ1+ (99%,99015463!2#!"&%3!2654&#!"47632#"'www@w   @ &&@ww@ww    B@ && @ Z /Ͱ/Ͱ/ /ְ Ͱ +Ͱ+ͱ!+ $9  $901$  $ >. 462"aa^(Ԗa^(ԖԖ]6/+/ Ͱ3/&Ͱ%/"Ͱ!/7/ְͰ+ͱ8+6+ !.6!6&!"!&+%!&+6..!"%&6.....@99 993/*+$9%&9"9! 9014732>'#"$&7>32'!!!27#"'!"&'Ѫz~u f:лV6B^hD%i(: ((%@*>6߅~̳ޛ 3?^BEa߀#9cr#!KL/ְͲ +@ +M+015463!2#!"&66767676'&6'.'&'.'&www@w C1 $$*=+T"wh%40C>9PC/+,+  /9F6(ww@w$)7 .3c M3IU/A*7U1.L4[N .QAg#%@) D:+E/=ֳ>$2+ͳ!"*$2+= +@+' +2=+ +@= + 2+.+5ͱF+6+ #?)+  #+ +++! +"#+?*?)+>?)+@ !"#)*>?................ #)?........@0154?5#"'&=4?546;2%6%66546;2+"&5#"'& wwww `G]B Gty]ty cB Cr +ͰA/63$Ͱ.2A$ +@A< +$A +@$) +/D/ְͰ?+%28Ͱ-28? +@83 +?8 +@? +8+ ͱE+01463!2#!"&73!2654&#!"5463!46;2!2#!+"&5!"&w@www^B@B^^BB^`@`@ @wwwwB^^B@B^^B@@`@`'7HP[./+Ͱ!/3Ͱ 2  ͳ!+&ͰF/DQ/LְͱR+ JM99&999FLO99901467&546;532!!+5#"&547&327!"+323!&#64'M: @nY*Yz--zY*n@ :t9pY-`]]`.X /2I$ tkQDDQ54!/@@3,$,3@@/!@&*0&& !P@00$pRV46?'&54632%'&5463276327632#"&/#"&/#"&546?#"&%%7,5TS]8T;/M77T7%>54&#!"www@w8(@(8!"5bb./ * =%/' #?7)(8ww@w7(88(#~$EE y &%O r    O"):8%_gqzh+ /Ͱ]/&I33)Ͱ/r/ְͰk+oͰo+ ͱs+k@   #&,`dh$9h#`df$9) @ "BMUam$9016$  $& $6&$ 47&6$32#"67>&&'&67>&"&#"%654'LlLe=Z=刈2CoiSƓ i 7J ?L.*K  Px.* ~p;_lL刈=Z=刈_tj`Q7  $ki'<Z :!   @! yy,ik*%E/3Ͱ2/ְͲ +@ + +ͱ+ 9990146$7%&$&57%7&]5ň%wnj&P'!|OzrSF 0y+Ͳ!%)222+ͳ#'+$2 /1/ְͲ +@ +2 +#Ͱ#$+'Ͱ'(++Ͳ+( +@+0 +22+$# 901463!2!5 ##!"&5546;!3!3!3!32))) ));;)&&&&@&&@ (6]4/-Ͱ /7/ ְ#2Ͱ2  +@  +8+ !'$9-4!#$9 %99'*/$9014762"'%+"'&7&54767%27% $&` ` t+8?::  ::A W>4>֬.`."e$IE&O &EI&{h<EvEEvm!"/ְͱ#+99901327>7327&#"&m:2+D?*%Zx/658:@#N >+)@ (oE=W'c:= E(o0La,/7Ͱ /SͰ]/3b/ְMͳ1M+Ͱ/1ͰM+!Ͱ!X+ͳ<X+'ͱc+M ,]999! 7EGS$9X9$999 7!'G$9]S990174676%.547#"&5467>3!##"&'&732>54.'&#"3267654.#"oYJ .H?LpKL1FE1@Z[@1G렄:$/Kce3:k[7'9C!5goS6j+=Y4%Q5">j@*Q.Q.R)A)(-R6B@X?ZHsG;@"$ECPN[RzsS`;v8\;)4^>0$/. 0$8].ggR4!8g;}R'!;5>R]q|z+/EͰo/dͲdo +da +h2[/z3VͰt2>32#"&'%632#"$'.547.767&#" $7>4&'&$ 462#"&462;2762+"'462#"&264&"654&#"^SAX[]8MmmMLmtG@W^>4}|0:M31$.>Wewpt+H+tpwwpttpSpQQ89Rj MM  ccSpQQ89R@Z@@Z5/9W>1^7R2>mnlMJ:^>h!yTRWWRTz%e;C,hWʺIKQQKIʹIKQQKI9RR98PP! MM ! cc9RR98PPoZ@@Z@i.G>WAI`ht /Ͱ^/QͲQ^ +QN +V2I/g3EͰc2%/?3.Ͱr/lͰ3/u/ְͰͰC+GͰGb+fͰfi+oͰo+ Ͱ "Ͱ"/v+C=?999GJO99b;)999f*UYX$9i,6+999o%'3.$99 09EI$9%"'=$9.();<$9lr+016*$9389015463!2#!"&32$654'>54&#"&'3264&#"'&&#"462"4762;2762+"'$462"4632#"&'!#,H3<&SG12HH2$< _$93HR4J44J1{z3A@:4J44J****~%=baab?'3I0k 12FGdH)!6 m+IJ44J633@@J44J6V**** *< /Ͱ-2 +@ + /Ͳ  +@ 6 +%2=/ְ Ͱ (+#Ͱ#++Ͱ2+9+23Ͱ30+ͱ>+#( 999 99+-993 990.9 )1<$901$  $32654632754&""&=#26=##"&='aa^rsRQsOpoOx|PrrRz~{]0/.3Ͳ +@ +)2/ 1/ְͰ+Ͱ+2#Ͱ2#(++ͱ2+9 9(#.9%&99  !"$901!2654632'54&"#"&%7265!#"&H7>3263232654.547'654'63276.#&#"'&547>'&#".'&'#"&%>327>7?67>?.'.*#"3>32#"'>;?757)  //7/ D+R>,7*  2(-#KcgA+![7>7>7 $&32>67>54.#"#.67>76'&#"'&#"767>3276'&'&#"';RKR/J#=$,9,+$UCS7'|ՀMLCF9vz NAG#/  -!$IOXp7s_"kb2)W+ rJ@    #    5/1Y|qK@ %(YQ&N EHv~\lshp4AM@=I>".)x.--ST(::(Y ! "1 [   / ,<ZxX-/U3%ͰC2%- +@%" +F2y/uְS2bͰL2bu +@be +I2z+buFPh999%-)I999015467&6?2?'#"&46326'&"/.7.?>>32'764&"?#"&'&/7264/YE.A %%%h%AUpIUxxULs T@ %hJ%D,FZCV sNUxfL.C %Jh%@/LexUJrVD %hJ%NHpVA %h&%%@.FZyUybJ/@ %Ji%CWpC-KfyUMt UC %hJ%@U sMUy^G,D %Jh%cv++3/Ͳ +{ +s/k/ְͰ+Ͳ +@ ++6+ :=1'+ (1'+++ :<:=+<:= #9(1' #9(1:<....(1:<....@99@ &7MSdnx$9 9999s@ c@I$9kAED$9016767672,32%#"'47%67>7>7&'&'&'>76763>7>&/&'.'767672#&'&546323267>7''+"&'7'7j+.=;. &JlLDf' % :/d B 4@ } ,+DCCQv!0$ && !IG_U% +6(:!TO?=/f-%fdL?6 #nk^/ !X "  ##  292Q41 5gN_     %1$I BS N.|nA '0@P`p4+d33%Ͱ 24% +@4 +=D4 +t33=ͱl22MT4 +33Mͱ|22(]4 +33(Ͱ0//ְ Ͱ +1ͱAQ22(Ͱ18+HX22aͱq22ah+x22ͱ22+22!ͳ)!+ͱ+./990(90146;2+"&%463!2#!"&!#"&=!;26=4&+"5;26=4&+"5;26=4&+";26=4&+"5;26=4&+"5;26=4&+";26=4&+"5;26=4&+"5;26=4&+"^BB^^BB^8((`(:FjB^(8``@B^^BB^^B(8(`("vEj^"8(/?O_o/?463!2#!"&;26=4&+"5;26=4&+"5;26=4&+"5;26=4&+"5;26=4&+"3!26=4&#!";26=4&+"5;26=4&+"5;26=4&+"5;26=4&+";26=4&+"5;26=4&+"5;26=4&+"5;26=4&+";26=4&+"5;26=4&+"5;26=4&+"5;26=4&+"5;26=4&+"&&&&@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@&&&&z@@@@@2@@@@@@@@@@@@@@`%k%/!&/ְͲ +@ + #Ͱ+Ͳ +@ +'+ %$9#!$$9!% $901462!762"&5#"&5$462"@8PpP8B\B@B\BDP88P.BB..BB.8$G #3CQf/Ͳ + +"2R/$ְ,Ͱ Ͱ,4+<ͳD<4+KͱS+,$"99499<9 DO$9014632#".4>32#"&#"#"4>32#".4>32#".4>32#"&TMLFTMLFpYv"?B+D?BJM&X=M{<&X=L|<'<{M=X&<|L=X&VFLMTFLMTPwoJPvoVӮvs.= ZY 2+"&7.@UUr_-$$-_r%&&5% /ְ2 ͱ!+0146762"'.-.&,&.$@B@$F@(BB(#<<%]|*.26:>B2C/8ְͰ?2@+ͱD+8<>$9@=9015467%467%62"'%&'"'%.-%-%-%+#+#6#+$*&!@@@@@@!&l@G@,l@`&@&@ @&p@&`$>>׭:ͽ  }:!7;A5+/Ͳ/5 +@/2 +5 Ͱ,/<Ͱ/ͳ?+%Ͱ!/B/ְͰ2+ Ͱ Ͱ "+,Ͱ<2," +,) +C+ 9, 99<)"99 9%9!9015!2#%!254#!5!2654#!432!32673!"!5!!&#"RWu?rt1SrF(N[\Ίensm?vd3ZpC~[R yK{T:֧IMމoy@7+|i%,AEK /Ͱ0Ͱ/ Ͱ6 9Ͱ93ͳK +IͰ&/'ͰB/CͰ/L/ְͰ+&2#Ͱ*Ͱ#+-Ͱ-<+ ͱM+#99<-BDFK$996#99 -<99IK9'?99015463!2#!"&7!2654'654.#!532#532#327##"&5!654&#"75!>32www@w~uk'JT7|wji> I'DH~?F8q ww@wsq*4p9O*sqhOZ^"(LE MM8Bzl5R[e/9Ͱ>/ Ͱ/#ͳV#+Ͱc/_ͰZ/ͳZ+3f/ְ Ͱ  +TͰT\+aͰaX+ͱg+ 06;$9T9a\UVZ$9>999 9#9c%9_@  ) STWX$90146326327>32##"&'#"'327'.546325.#"3264&#" #".264&#"462#"&zUIr19rsswOIr37UCY? @!'G2LI*?YUI+?YY? $G2#(mnnMLGWzXW>=Wy\GrPk\G;@Y=$2G%,Y%,Y~Z  2G [mmm>WXzWW1DV`j /Ͱ_/dͰi/ZͰ"/Ͱ/k/ְͰX+aͰaf+]Ͱ] +ͱl+X$28ER$9fa"Z_$9_&)+PU$9dAC999i@  ,2%5@WX\]$9015463!2#!"&327326?264&#""&#"%.#"4632'&#"676&/632#"4632#"'2654&"www@wL6$ G.2IGffGHel #  G-6L"8(- 07 ((}*: ('88';D10DD01,7L77L7ww@w5L,:D1zefeG,:L^P8 8  9 7P7I`DD`Du'66'&77V->M\-+L+3AͰ2]/^+AL ?B$901'.?67&>7%.'>%67%7.'6?%7&?a0#Ov "N\$> P(1#00/6 'I]"RE<98 1G#9  ($=!F "\HiTe<?}8J$\ 9%d,6?=SVY]C j# %N#" H@)1;C'/33ͳ23$2-'+>3#Ͱ28/ D/%ְ Ͱ22+ %+Ͱ/+ͳ/ %+=Ͱ +ͳA+ͱE+6>q+ 2;q+ 3.4  4;.... 34;.......@-0B9901546;>3!232+"&=!"&=#"&264&"%!.#!"264&"]ibbi]pp`pp`^^^Y @ c^^^]^^]]PppPPppPp^^^e^^^3;EM1+ (33ͳ<=$271+H3-Ͱ$2B/Ͱ Ͱ2N/ְ5Ͱ59+GͰGK+ͱO+6>q+ .<Eq+ =.>>E....<=>E........@5/99,-99G')* $9K$%99!"99B-:L9901546;>;5463!23232+"&=!"&=#"&264&"%!.#!"264&"]ib@bi]pp`pp`^^^Y @ c^^^ ]^^]]@PppP@@PppP@p^^^e^^^ 3S4/.ְ12'Ͱ$2'. +@'! +@' +@' +.' +@. +@. +@. +5+'. $901647#"&47#"&4762++#!#!"&5467!" &&4&&&2 $$ 2&4&4&44&m4&m4&&##& $:P />ͰFͲF +@FB +M/,Ͱ7/Ͱ /Q/ְ%Ͱ%+Ͱ3Ͱ3/R+% 93@   ;I$99>FDI99M0999,(.39997%999$9  901$  $32763232654'&$#"32763 32654'&!"32763232654'&#"aa^) -g+(~̠4#z##ə0  o*a^(*%D= )/IK/%#!| #(* g  s" :NUk8+ /Ͱ//L/?ͲL? +@LD +/V/ְͰ+ ͱW+ 3;CPR$9/8".1;QT$9L#('0M$9015463!2#!"&73!2654&#!"5%>36'&%#!"&463!2&'$'#&7&Q::QQ::QG((((2 84@ao   Ug AU :QQ::QQ:(((( G;.} 0 T@43f= t !-;<JXfuv762"'?432#"5?632#"'?432#"5?4632#"&537632#"'7632#"'74632#"'732?.#"7462"&'7>2"&'732765?4'&"7567632"&/47632632#!.>  C  E  F  )  J  N  O  /!R U     ;  _U`59uu  ~ ~   |   ,                J|   rq "vu )9:+ Ͱ/Ͱ'/ Ͱ7//:/;+99 '990115 $7 $&5 $7 $&5 $7 $&546$  $&ww`ww`ww`bb`ΪTVVTEvEEvŪTVVTEvEEvŪTVVTEvEEvŀEvEEvEEvEEvW\gyQ+/ͰJ/Ͱ/@Ͱ/zͰ-2//ְͰj+8Ͱ8+zͰz+ ͱ+j@ W(*OXZ]dyu$98:nt9992_99z>M99@CJ{$9JQ!$OXZ$9G]99M9@>_99(:dh$9z5nux$9901463!2#!"&7!!"&5!>766767.76;2632#"&'#"/&'&767%67.'&'674767&54&5&'%!&'&'3274'&8((`8(8((8`(8 ^U 47D$    7[!3;:A0?ݫY  A4U3IL38k Cx JL0@(8(`((88H8((g- Up~R2(/{EJ1&(!;  (X6CmVo8%(*\ 9 JQ\/Ͱ/KͰ/R/ְͰ+GͰG+KͰK+ ͱS+6=+ >= !}F+ '*<8>m+ 32,-1+ '('*+)'*+ + <9<8+9<8 #9('* #9)9@ !'*,-238<=>()9...............@ !'*,-238<=>()9...............@J99GHI999K+01:$9./L999%+/16I$9KQ901463!2#!"&7!!"&5!3367653335!3#'.'##'&'35!!&'&'8((`8(8((8`(8iFFZcrcZx @(8(`((88H8(k" kkJ ! k 9 LSn/Ͱ/MͰ/T/ְͰ+MͰM+ ͱU+-./378>$9M9902456N$9699MS901463!2#!"&7!!"&5!!5#7>;#!5#35!3#&'&/35!3#!&'&'8((`8(8((8`(8-Kg kL#DCJg  jLDDSx @(8(`((88H8(j jjkk kk 9 1<C/Ͱ!/2Ͱ3/.3,Ͱ/=Ͱ/D/ְͰ+=Ͱ8 'Ͱ=+ ͱE+ !-/23$9'>9!09932'9=C901463!2#!"&7!!"&5!!5#5327>54&'&#!3#32#!&'&'8((`8(8((8`(8 G]L*COJ?0R\\x48>/x @(8(`((88H8(jRQxk !RY~ 9 #+2+/Ͱ+/'Ͱ/,Ͱ/3/ְͰ%+2)Ͳ)% +@)# +)+,Ͱ,+ ͱ4+)% 9,!9-9+ "999'!9,2901463!2#!"&7!!"&5!57 462"!&'&'8((`8(8((8`(8@pppx @(8(`((88H8(pppp 9  3;?CGKR2+7Ͱ/Ͱ;/(Ͳ(; +@(& +D2AMPU$9X^901463!2#!"&7!!"&5!546;76#"/#"&32764'.3276'.!&'&'8((`8(8((8`(8 WW6&446dd$x @(8(`((88H8( )5]]$59955{{ 9 ,<Ck/Ͱ*/:3!Ͱ12/=Ͱ/D/ְͰ+&Ͱ& +=Ͱ=+ ͱE+=-.9915:>$9=C901463!2#!"&7!!"&5!463!2#!"&%5632#"'!&'&'8((`8(8((8`(8L44LL44L  x @(8(`((88H8(4LL44LLZ  w 9 0@T[/Ͱ/UͰ/\/ְͰ+UͰU+ ͱ]+6?#+ 12:9129:....129:....@&99UBF99DNV999".&'>/.$&?'&6?6/!&'&'8((`8(8((8`(8~ 3  3  ?  ? ; 3  3@x @(8(`((88H8(-- & & U?     &  &` 9 '6h)/$Ͱ/7/ְͰ +!Ͱ!+Ͱ&28+! 9999$)999$)'99 &$901!67&54632".'654&#"327#'. 'XyzOvд:C;A:25@Ң>;eaAɢ/PRAids`W`H( ' gQWZc[-05rn"&*-Q./ְͰ+2#Ͱ'2#,+ ͱ/+$9# "$9,!$)+$9014762"'&?'%%-%% "3,3"",">[ NM[N o")" )) "nngng]xߴ]x#Z+'Ͱ<2./P34ͰJ2X/B3 Ͱ[/ְ$Ͱ$?+ͱ\+$!999? 999999.')9X,H$9 $901467&546326$32#"&#!+.327.'#"&5463232654&#"632#".#"n\ u_MK'oGԨ|g? CM7MM5,QAAIQqAy{b& BL4PJ9+OABIRo?zn6'+s:.z zcIAC65D*DRRD*wya$, @B39E*DRRD*'/7 /"Ͱ&/Ͱ/+Ͱ//8/ְͰ+Ͱ+7Ͱ73+ ͱ9+9999  #(-$97059931499&" #99$'99 14$9+),99/(-99016$  $&7&47' 6&  7'"'627& 6'LlLZ&>ʫ|RRRR«ZZlLRR>ZZZY«|R!Z +Ͱ/3Ͱ2"/ְͲ +@ ++Ͳ +@ +#+99 99014$7 >54' $&_ff_ʎ-ff`-޶Lc@_/d/ְ Ͳ +@  + G+[ͱe+ 9G5;NQ_$9016721>?>././76&/7>?>?>./&31#"$&(@8!IH2hM>'  )-* h'N'!'Og,R"/!YQG54'675#&#"432#"432#"2654&"3&547#6323#3275#"=3235#47##www@w(DL+`N11MZ % N92Z2<)UmQ// +)&')-S99kUeid=R;XYtWW-Ya^"![Y-L6#)|!'(<`X;_"# /Ͱ/3#/$+9015463!2#!"& 3##.'www@wpCWU3D/9$H ww@wFML'b;0bqG9+Iw /Ͱ$9<%(9998 #3>$9014>32#"'.7>32>4."&'&>767&5462#"'#"&'9]v @C$39aLL²L4 &) @.&FD(=GqqrO<3>5-w؜\% L²LLarh({󿵂72765'./"#"&'& }1R<2" 7MW'$  ;IS7@5sQ@@)R#DvTA ; 0x I)!:> +)C 6>&8CO[6/GͰS2M/Y3+Ͱ$/A3Ͳ$ +@$ +\/ְͰ(+Dͳ9D(+"Ͱ"/9ͰDJ+PͰPV+/ͱ]+"999$9D(>9PJ +6$9V49G6'/24$9M(9+9$ <$9014$32&#"#".'7$3264&#"6$32'#"$3264&#"32654&#"32654&#"MŰ9'#!0>R H|B+)22)+Bu7ǖD[B+)11)+B-(33(--'44'-ZNJ '31R23uWm% '31R23-,,--,,-&7632#"'%#"'.5 %&"! ; `u%( (!]#c &76#"'%#"'.5%&7 ##!!  (%P_"'(!7+4Iy/ Ͳ  +  +G/9Ͳ9G +@9> +)/ J/:ְCͲ:C +@:5 +C%+ͱK+C: ) $99G$99)% 12$9 99014766$32#"$'&6?6332>4.#"#!"&546;46;2#!"&('kzz䜬m IwhQQhbF*@&@@*eozz   _hQнQGB'(&@`@ D+ Ͱ//ְ Ͱ +ͱ+  $9$901$  $ >. aa^Nfffa^ffff>g/BHm333bͲ7654'&#!"#"&#"#"&54>765'46.'."&>..**"+8#  #Q3,,++#-:#"$$ /:yu #3=GWak:/^334Ͳ4: +@4 +@4Y +1/(Ͱ /ͰU/LͰb/fͱB22bf +@b +@b> +l/ְ2Ͱ"2=+>26ͰF26X+b2[Ͱj2m+= $%$9X6-,HI$9015463!2#!"&!+"&46;25463!2#!"&!+"&546;25463!2#!"&!+"&546;28(@(88((88(@(88((88(@(88((8@(88(@(88`.` @(88(@(88x ` @(88(@(88`.%Q/Ͱ/ ͳ +$&/'+$!99"$999 $9  9901632%&546 #"'632 &547%#"~\h ~\h\~\~ V VV V5j /ͰͰ/(Ͱ4/Ͱ-6/ְͰ+*2 ͱ7+"999!$9("%994&*2$9015463!2#!"&327264&#"'64'73264&"&#"www@w}XS>~}}XT==TX}}~>SXww@w}9xX}}~:xx:~}}Xx9/>JXgsNr/kt/ְͰ2?+Fͱu+ )03$9? 47;$9F9kr 9016$327627 $&327>7>.4762#"/5462"&4762"/&4?62#"'46;2+"o@5D.D@Yo1 *"T0l,  Z [E  [  Z Z  [ ``1oY@D.D5@ooS0 (T" 02 ,l [  Z)`` Z  [ [  Z =BH!_<ϙwiϙwi  U3U3]yn2@ zZ@55 zZZ@,_s@ @(@@- MM- MM @@ -`b $ 648""""""@N@ ,@  mo)@@   'D9>XRX8` 2  r ` xJT6(R@z (R.j !֜8~*pž:vܠBT袨(Ȧ|4ȬHбT ̴ffҸ>d0R6N(*|.vƒdȜzʸ8̼͚&n>Ҡ*x lVrݤބ2"2v0NB6,.HzNNNNNNNNNNNNNNNNNNNNNNNNNNNN^ ~ ~  . & $  0   * <( d 0zCopyright 2014 Adobe Systems Incorporated. All rights reserved.FontAwesomeRegularpyrs: FontAwesome: 2012FontAwesome RegularVersion 4.1.0 2013FontAwesomePlease refer to the Copyright section for the font trademark attribution notices.Fort AwesomeDave Gandyhttp://fontawesome.iohttp://fontawesome.io/license/Webfont 1.0Wed May 14 15:41:29 2014zZ      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopq rstuvwxyz{|}~     " !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~uni00A0uni2000uni2001uni2002uni2003uni2004uni2005uni2006uni2007uni2008uni2009uni200Auni202Funi205Funi25FCglassmusicsearchenvelopeheartstar star_emptyuserfilmth_largethth_listokremovezoom_inzoom_outoffsignalcogtrashhomefile_alttimeroad download_altdownloaduploadinbox play_circlerepeatrefreshlist_altlockflag headphones volume_off volume_down volume_upqrcodebarcodetagtagsbookbookmarkprintcamerafontbolditalic text_height text_width align_left align_center align_right align_justifylist indent_left indent_rightfacetime_videopicturepencil map_markeradjusttinteditsharecheckmove step_backward fast_backwardbackwardplaypausestopforward fast_forward step_forwardeject chevron_left chevron_right plus_sign minus_sign remove_signok_sign question_sign info_sign screenshot remove_circle ok_circle ban_circle arrow_left arrow_rightarrow_up arrow_down share_alt resize_full resize_smallexclamation_signgiftleaffireeye_open eye_close warning_signplanecalendarrandomcommentmagnet chevron_up chevron_downretweet shopping_cart folder_close folder_openresize_verticalresize_horizontal bar_chart twitter_sign facebook_sign camera_retrokeycogscomments thumbs_up_altthumbs_down_alt star_half heart_emptysignout linkedin_signpushpin external_linksignintrophy github_sign upload_altlemonphone check_emptybookmark_empty phone_signtwitterfacebookgithubunlock credit_cardrsshddbullhornbell certificate hand_right hand_lefthand_up hand_downcircle_arrow_leftcircle_arrow_rightcircle_arrow_upcircle_arrow_downglobewrenchtasksfilter briefcase fullscreengrouplinkcloudbeakercutcopy paper_clipsave sign_blankreorderulol strikethrough underlinetablemagictruck pinterestpinterest_signgoogle_plus_sign google_plusmoney caret_downcaret_up caret_left caret_rightcolumnssort sort_downsort_up envelope_altlinkedinundolegal dashboard comment_alt comments_altboltsitemapumbrellapaste light_bulbexchangecloud_download cloud_uploaduser_md stethoscopesuitcasebell_altcoffeefood file_text_altbuildinghospital ambulancemedkit fighter_jetbeerh_signf0fedouble_angle_leftdouble_angle_rightdouble_angle_updouble_angle_down angle_left angle_rightangle_up angle_downdesktoplaptoptablet mobile_phone circle_blank quote_left quote_rightspinnercirclereply github_altfolder_close_altfolder_open_alt expand_alt collapse_altsmilefrownmehgamepadkeyboardflag_altflag_checkeredterminalcode reply_allstar_half_emptylocation_arrowcrop code_forkunlink_279 exclamation superscript subscript_283 puzzle_piece microphonemicrophone_offshieldcalendar_emptyfire_extinguisherrocketmaxcdnchevron_sign_leftchevron_sign_rightchevron_sign_upchevron_sign_downhtml5css3anchor unlock_altbullseyeellipsis_horizontalellipsis_vertical_303 play_signticketminus_sign_alt check_minuslevel_up level_down check_sign edit_sign_312 share_signcompasscollapse collapse_top_317eurgbpusdinrjpyrubkrwbtcfile file_textsort_by_alphabet_329sort_by_attributessort_by_attributes_alt sort_by_ordersort_by_order_alt_334_335 youtube_signyoutubexing xing_sign youtube_playdropbox stackexchange instagramflickradnf171bitbucket_signtumblr tumblr_signlong_arrow_down long_arrow_uplong_arrow_leftlong_arrow_rightwindowsandroidlinuxdribbleskype foursquaretrellofemalemalegittipsun_366archivebugvkweiborenren_372stack_exchange_374arrow_circle_alt_left_376dot_circle_alt_378 vimeo_square_380 plus_square_o_382_383_384_385_386_387_388_389uniF1A0f1a1_392_393f1a4_395_396_397_398_399_400f1ab_402_403_404uniF1B1_406_407_408_409_410_411_412_413_414_415_416_417_418_419uniF1C0uniF1C1_422_423_424_425_426_427_428_429_430_431_432_433_434uniF1D0uniF1D1uniF1D2_438_439uniF1D5uniF1D6uniF1D7_443_444_445_446_447_448_449uniF1E0_451_452_453_454_455_456_457_458_459_460_461_462_463_464_466_467_468_469_470_471_472_473_474_475_476_477_478_479KPXYF+X!YKRX!Y+\XY+Ssukui-panel-3.0.6.4/ukui-calendar/lunarcalendarwidget/lunarcalendarmonthitem.h0000644000175000017500000001737714204636772026062 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #ifdef quc #if (QT_VERSION < QT_VERSION_CHECK(5,7,0)) #include #else #include #endif class QDESIGNER_WIDGET_EXPORT LunarCalendarItem : public QWidget #else class LunarCalendarMonthItem : public QWidget #endif { Q_OBJECT Q_ENUMS(DayType) Q_ENUMS(SelectType) Q_PROPERTY(bool select READ getSelect WRITE setSelect) Q_PROPERTY(bool showLunar READ getShowLunar WRITE setShowLunar) Q_PROPERTY(QString bgImage READ getBgImage WRITE setBgImage) Q_PROPERTY(SelectType selectType READ getSelectType WRITE setSelectType) Q_PROPERTY(QDate date READ getDate WRITE setDate) Q_PROPERTY(QString lunar READ getLunar WRITE setLunar) Q_PROPERTY(DayType dayType READ getDayType WRITE setDayType) Q_PROPERTY(QColor borderColor READ getBorderColor WRITE setBorderColor) Q_PROPERTY(QColor weekColor READ getWeekColor WRITE setWeekColor) Q_PROPERTY(QColor superColor READ getSuperColor WRITE setSuperColor) Q_PROPERTY(QColor lunarColor READ getLunarColor WRITE setLunarColor) Q_PROPERTY(QColor currentTextColor READ getCurrentTextColor WRITE setCurrentTextColor) Q_PROPERTY(QColor otherTextColor READ getOtherTextColor WRITE setOtherTextColor) Q_PROPERTY(QColor selectTextColor READ getSelectTextColor WRITE setSelectTextColor) Q_PROPERTY(QColor hoverTextColor READ getHoverTextColor WRITE setHoverTextColor) Q_PROPERTY(QColor currentLunarColor READ getCurrentLunarColor WRITE setCurrentLunarColor) Q_PROPERTY(QColor otherLunarColor READ getOtherLunarColor WRITE setOtherLunarColor) public: enum DayType { DayType_MonthPre = 0, //上月剩余天数 DayType_MonthNext = 1, //下个月的天数 DayType_MonthCurrent = 2, //当月天数 DayType_WeekEnd = 3 //周末 }; enum SelectType { SelectType_Rect = 0, //矩形背景 SelectType_Circle = 1, //圆形背景 SelectType_Triangle = 2, //带三角标 SelectType_Image = 3 //图片背景 }; explicit LunarCalendarMonthItem(QWidget *parent = 0); QMap> worktime; protected: void enterEvent(QEvent *); void leaveEvent(QEvent *); void mousePressEvent(QMouseEvent *); void mouseReleaseEvent(QMouseEvent *); void paintEvent(QPaintEvent *); void drawBg(QPainter *painter); void drawBgCurrent(QPainter *painter, const QColor &color); void drawBgHover(QPainter *painter, const QColor &color); void drawMonth(QPainter *painter); private: bool hover; //鼠标是否悬停 bool pressed; //鼠标是否按下 bool select; //是否选中 bool showLunar; //显示农历 QString bgImage; //背景图片 SelectType selectType; //选中模式 QDate date; //当前日期 QString lunar; //农历信息 DayType dayType; //当前日类型 QColor borderColor; //边框颜色 QColor weekColor; //周末颜色 QColor superColor; //角标颜色 QColor lunarColor; //农历节日颜色 QColor currentTextColor; //当前月文字颜色 QColor otherTextColor; //其他月文字颜色 QColor selectTextColor; //选中日期文字颜色 QColor hoverTextColor; //悬停日期文字颜色 QColor currentLunarColor; //当前月农历文字颜色 QColor otherLunarColor; //其他月农历文字颜色 QColor selectLunarColor; //选中日期农历文字颜色 QColor hoverLunarColor; //悬停日期农历文字颜色 QColor currentBgColor; //当前月背景颜色 QColor otherBgColor; //其他月背景颜色 QColor selectBgColor; //选中日期背景颜色 QColor hoverBgColor; //悬停日期背景颜色 public: bool getSelect() const; bool getShowLunar() const; QString getBgImage() const; SelectType getSelectType() const; QDate getDate() const; QString getLunar() const; DayType getDayType() const; QColor getBorderColor() const; QColor getWeekColor() const; QColor getSuperColor() const; QColor getLunarColor() const; QColor getCurrentTextColor() const; QColor getOtherTextColor() const; QColor getSelectTextColor() const; QColor getHoverTextColor() const; QColor getCurrentLunarColor() const; QColor getOtherLunarColor() const; QColor getSelectLunarColor() const; QColor getHoverLunarColor() const; QColor getCurrentBgColor() const; QColor getOtherBgColor() const; QColor getSelectBgColor() const; QColor getHoverBgColor() const; QSize sizeHint() const; QSize minimumSizeHint() const; public Q_SLOTS: //设置是否选中 void setSelect(bool select); //设置是否显示农历信息 void setShowLunar(bool showLunar); //设置背景图片 void setBgImage(const QString &bgImage); //设置选中背景样式 void setSelectType(const SelectType &selectType); //设置日期 void setDate(const QDate &date); //设置农历 void setLunar(const QString &lunar); //设置类型 void setDayType(const DayType &dayType); //设置日期/农历/类型 void setDate(const QDate &date, const QString &lunar, const DayType &dayType); //设置边框颜色 void setBorderColor(const QColor &borderColor); //设置周末颜色 void setWeekColor(const QColor &weekColor); //设置角标颜色 void setSuperColor(const QColor &superColor); //设置农历节日颜色 void setLunarColor(const QColor &lunarColor); //设置当前月文字颜色 void setCurrentTextColor(const QColor ¤tTextColor); //设置其他月文字颜色 void setOtherTextColor(const QColor &otherTextColor); //设置选中日期文字颜色 void setSelectTextColor(const QColor &selectTextColor); //设置悬停日期文字颜色 void setHoverTextColor(const QColor &hoverTextColor); //设置当前月农历文字颜色 void setCurrentLunarColor(const QColor ¤tLunarColor); //设置其他月农历文字颜色 void setOtherLunarColor(const QColor &otherLunarColor); Q_SIGNALS: void clicked(const QDate &date, const LunarCalendarMonthItem::DayType &dayType); void monthMessage(const QDate &date, const LunarCalendarMonthItem::DayType &dayType); }; #endif // LUNARCALENDARMONTHITEM_H ukui-panel-3.0.6.4/ukui-calendar/lunarcalendarwidget/ui_frmlunarcalendarwidget.h0000644000175000017500000001735214203402514026514 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include #include #include #include #include #include "lunarcalendarwidget.h" QT_BEGIN_NAMESPACE class Ui_frmLunarCalendarWidget { public: QVBoxLayout *verticalLayout; LunarCalendarWidget *lunarCalendarWidget; QWidget *widgetBottom; QHBoxLayout *horizontalLayout; // QLabel *labCalendarStyle; // QComboBox *cboxCalendarStyle; // QLabel *labSelectType; // QComboBox *cboxSelectType; // QLabel *labWeekNameFormat; // QComboBox *cboxWeekNameFormat; // QCheckBox *ckShowLunar; QSpacerItem *horizontalSpacer; void setupUi(QWidget *frmLunarCalendarWidget) { if (frmLunarCalendarWidget->objectName().isEmpty()) frmLunarCalendarWidget->setObjectName(QString::fromUtf8("frmLunarCalendarWidget")); frmLunarCalendarWidget->resize(600, 500); verticalLayout = new QVBoxLayout(frmLunarCalendarWidget); verticalLayout->setObjectName(QString::fromUtf8("verticalLayout")); lunarCalendarWidget = new LunarCalendarWidget(frmLunarCalendarWidget); lunarCalendarWidget->setObjectName(QString::fromUtf8("lunarCalendarWidget")); QSizePolicy sizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding); sizePolicy.setHorizontalStretch(0); sizePolicy.setVerticalStretch(0); sizePolicy.setHeightForWidth(lunarCalendarWidget->sizePolicy().hasHeightForWidth()); lunarCalendarWidget->setSizePolicy(sizePolicy); verticalLayout->addWidget(lunarCalendarWidget); widgetBottom = new QWidget(frmLunarCalendarWidget); widgetBottom->setObjectName(QString::fromUtf8("widgetBottom")); horizontalLayout = new QHBoxLayout(widgetBottom); horizontalLayout->setObjectName(QString::fromUtf8("horizontalLayout")); horizontalLayout->setContentsMargins(0, 0, 0, 0); // labCalendarStyle = new QLabel(widgetBottom); // labCalendarStyle->setObjectName(QString::fromUtf8("labCalendarStyle")); // horizontalLayout->addWidget(labCalendarStyle); // cboxCalendarStyle = new QComboBox(widgetBottom); // cboxCalendarStyle->addItem(QString()); // cboxCalendarStyle->setObjectName(QString::fromUtf8("cboxCalendarStyle")); // cboxCalendarStyle->setMinimumSize(QSize(90, 0)); // horizontalLayout->addWidget(cboxCalendarStyle); // labSelectType = new QLabel(widgetBottom); // labSelectType->setObjectName(QString::fromUtf8("labSelectType")); // horizontalLayout->addWidget(labSelectType); // cboxSelectType = new QComboBox(widgetBottom); // cboxSelectType->addItem(QString()); // cboxSelectType->addItem(QString()); // cboxSelectType->addItem(QString()); // cboxSelectType->addItem(QString()); // cboxSelectType->setObjectName(QString::fromUtf8("cboxSelectType")); // cboxSelectType->setMinimumSize(QSize(90, 0)); // horizontalLayout->addWidget(cboxSelectType); // labWeekNameFormat = new QLabel(widgetBottom); // labWeekNameFormat->setObjectName(QString::fromUtf8("labWeekNameFormat")); // horizontalLayout->addWidget(labWeekNameFormat); // cboxWeekNameFormat = new QComboBox(widgetBottom); // cboxWeekNameFormat->addItem(QString()); // cboxWeekNameFormat->addItem(QString()); // cboxWeekNameFormat->addItem(QString()); // cboxWeekNameFormat->addItem(QString()); // cboxWeekNameFormat->setObjectName(QString::fromUtf8("cboxWeekNameFormat")); // cboxWeekNameFormat->setMinimumSize(QSize(90, 0)); // horizontalLayout->addWidget(cboxWeekNameFormat); // ckShowLunar = new QCheckBox(widgetBottom); // ckShowLunar->setObjectName(QString::fromUtf8("ckShowLunar")); // ckShowLunar->setChecked(true); // horizontalLayout->addWidget(ckShowLunar); horizontalSpacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); horizontalLayout->addItem(horizontalSpacer); // verticalLayout->addWidget(widgetBottom); retranslateUi(frmLunarCalendarWidget); QMetaObject::connectSlotsByName(frmLunarCalendarWidget); } // setupUi void retranslateUi(QWidget *frmLunarCalendarWidget) { frmLunarCalendarWidget->setWindowTitle(QApplication::translate("frmLunarCalendarWidget", "Form", nullptr)); // labCalendarStyle->setText(QApplication::translate("frmLunarCalendarWidget", "\346\225\264\344\275\223\346\240\267\345\274\217", nullptr)); // cboxCalendarStyle->setItemText(0, QApplication::translate("frmLunarCalendarWidget", "\347\272\242\350\211\262\351\243\216\346\240\274", nullptr)); // labSelectType->setText(QApplication::translate("frmLunarCalendarWidget", "\351\200\211\344\270\255\346\240\267\345\274\217", nullptr)); // cboxSelectType->setItemText(0, QApplication::translate("frmLunarCalendarWidget", "\347\237\251\345\275\242\350\203\214\346\231\257", nullptr)); // cboxSelectType->setItemText(1, QApplication::translate("frmLunarCalendarWidget", "\345\234\206\345\275\242\350\203\214\346\231\257", nullptr)); // cboxSelectType->setItemText(2, QApplication::translate("frmLunarCalendarWidget", "\350\247\222\346\240\207\350\203\214\346\231\257", nullptr)); // cboxSelectType->setItemText(3, QApplication::translate("frmLunarCalendarWidget", "\345\233\276\347\211\207\350\203\214\346\231\257", nullptr)); // labWeekNameFormat->setText(QApplication::translate("frmLunarCalendarWidget", "\346\230\237\346\234\237\346\240\274\345\274\217", nullptr)); // cboxWeekNameFormat->setItemText(0, QApplication::translate("frmLunarCalendarWidget", "\347\237\255\345\220\215\347\247\260", nullptr)); // cboxWeekNameFormat->setItemText(1, QApplication::translate("frmLunarCalendarWidget", "\346\231\256\351\200\232\345\220\215\347\247\260", nullptr)); // cboxWeekNameFormat->setItemText(2, QApplication::translate("frmLunarCalendarWidget", "\351\225\277\345\220\215\347\247\260", nullptr)); // cboxWeekNameFormat->setItemText(3, QApplication::translate("frmLunarCalendarWidget", "\350\213\261\346\226\207\345\220\215\347\247\260", nullptr)); // ckShowLunar->setText(QApplication::translate("frmLunarCalendarWidget", "\346\230\276\347\244\272\345\206\234\345\216\206", nullptr)); } // retranslateUi }; namespace Ui { class frmLunarCalendarWidget: public Ui_frmLunarCalendarWidget {}; } // namespace Ui QT_END_NAMESPACE #endif // UI_FRMLUNARCALENDARWIDGET_H ukui-panel-3.0.6.4/ukui-calendar/lunarcalendarwidget/lunarcalendarinfo.h0000644000175000017500000000701314203402514024753 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #ifdef quc #if (QT_VERSION < QT_VERSION_CHECK(5,7,0)) #include #else #include #endif class QDESIGNER_WIDGET_EXPORT LunarCalendarInfo : public QObject #else class LunarCalendarInfo : public QObject #endif { Q_OBJECT public: static LunarCalendarInfo *Instance(); explicit LunarCalendarInfo(QObject *parent = 0); //计算是否闰年 bool isLoopYear(int year); //计算指定年月该月共多少天 int getMonthDays(int year, int month); //计算指定年月对应到该月共多少天 int getTotalMonthDays(int year, int month); //计算指定年月对应星期几 int getFirstDayOfWeek(int year, int month, bool FirstDayisSun); //计算国际节日 QString getHoliday(int month, int day); //计算二十四节气 QString getSolarTerms(int year, int month, int day); //计算农历节日(必须传入农历年份月份) QString getLunarFestival(int month, int day); //计算农历年 天干+地支+生肖 QString getLunarYear(int year); //计算指定年月日农历信息,包括公历节日和农历节日及二十四节气 void getLunarCalendarInfo(int year, int month, int day, QString &strHoliday, QString &strSolarTerms, QString &strLunarFestival, QString &strLunarYear, QString &strLunarMonth, QString &strLunarDay); //获取指定年月日农历信息 QString getLunarInfo(int year, int month, int day, bool yearInfo, bool monthInfo, bool dayInfo); QString getLunarYearMonthDay(int year, int month, int day); QString getLunarMonthDay(int year, int month, int day); QString getLunarDay(int year, int month, int day); private: static QScopedPointer self; QList lunarCalendarTable; //农历年表 QList springFestival; //春节公历日期 QList lunarData; //农历每月数据 QList chineseTwentyFourData; //农历二十四节气数据 QList monthAdd; //公历每月前面的天数 QList listDayName; //农历日期名称集合 QList listMonthName; //农历月份名称集合 QList listSolarTerm; //二十四节气名称集合 QList listTianGan; //天干名称集合 QList listDiZhi; //地支名称集合 QList listShuXiang; //属相名称集合 }; #endif // LUNARCALENDARINFO_H ukui-panel-3.0.6.4/ukui-calendar/lunarcalendarwidget/main.qrc0000644000175000017500000000023514203402514022545 0ustar fengfeng image/bg_calendar.png image/fontawesome-webfont.ttf ukui-panel-3.0.6.4/ukui-calendar/lunarcalendarwidget/lunarcalendarwidget.pro0000644000175000017500000000203514203402514025653 0ustar fengfeng#------------------------------------------------- # # Project created by QtCreator 2017-01-05T22:11:54 # #------------------------------------------------- QT += core gui greaterThan(QT_MAJOR_VERSION, 4): QT += widgets TARGET = lunarcalendarwidget TEMPLATE = app QMAKE_CXXFLAGS += -std=c++11 MOC_DIR = temp/moc RCC_DIR = temp/rcc UI_DIR = temp/ui OBJECTS_DIR = temp/obj DESTDIR = $$PWD/../bin CONFIG += qt warn_off RESOURCES += main.qrc CONFIG += \ link_pkgconfig \ PKGCONFIG += gsettings-qt SOURCES += main.cpp SOURCES += frmlunarcalendarwidget.cpp SOURCES += lunarcalendaritem.cpp SOURCES += lunarcalendarinfo.cpp SOURCES += lunarcalendarwidget.cpp HEADERS += frmlunarcalendarwidget.h HEADERS += lunarcalendaritem.h HEADERS += lunarcalendarinfo.h HEADERS += lunarcalendarwidget.h FORMS += frmlunarcalendarwidget.ui INCLUDEPATH += $$PWD ukui-panel-3.0.6.4/ukui-calendar/lunarcalendarwidget/lunarcalendarmonthitem.cpp0000644000175000017500000003066014203402514026363 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see LunarCalendarMonthItem::LunarCalendarMonthItem(QWidget *parent) : QWidget(parent) { hover = false; pressed = false; select = false; select = false; showLunar = true; bgImage = ":/image/bg_calendar.png"; selectType = SelectType_Rect; date = QDate::currentDate(); lunar = "初一"; dayType = DayType_MonthCurrent; //实时监听主题变化 const QByteArray id("org.ukui.style"); QGSettings * fontSetting = new QGSettings(id, QByteArray(), this); connect(fontSetting, &QGSettings::changed,[=](QString key) { if(fontSetting->get("style-name").toString() == "ukui-default") { weekColor = QColor(255, 255, 255); currentTextColor = QColor(255, 255, 255); otherTextColor = QColor(255, 255, 255,40); otherLunarColor = QColor(255, 255, 255,40); currentLunarColor = QColor(255, 255, 255,90); lunarColor = QColor(255, 255, 255,90); } else if(fontSetting->get("style-name").toString() == "ukui-light") { weekColor = QColor(0, 0, 0); currentTextColor = QColor(0, 0, 0); otherTextColor = QColor(0,0,0,40); otherLunarColor = QColor(0,0,0,40); currentLunarColor = QColor(0,0,0,90); lunarColor = QColor(0,0,0,90); } else if(fontSetting->get("style-name").toString() == "ukui-dark") { weekColor = QColor(255, 255, 255); currentTextColor = QColor(255, 255, 255); otherTextColor = QColor(255, 255, 255,40); otherLunarColor = QColor(255, 255, 255,40); currentLunarColor = QColor(255, 255, 255,90); lunarColor = QColor(255, 255, 255,90); } }); if(fontSetting->get("style-name").toString() == "ukui-light") { weekColor = QColor(0, 0, 0); currentTextColor = QColor(0, 0, 0); otherTextColor = QColor(0,0,0,40); otherLunarColor = QColor(0,0,0,40); currentLunarColor = QColor(0,0,0,90); lunarColor = QColor(0,0,0,90); } else { weekColor = QColor(255, 255, 255); currentTextColor = QColor(255, 255, 255); otherTextColor = QColor(255, 255, 255,40); otherLunarColor = QColor(255, 255, 255,40); currentLunarColor = QColor(255, 255, 255,90); lunarColor = QColor(255, 255, 255,90); } borderColor = QColor(180, 180, 180); superColor = QColor(255, 129, 6); selectTextColor = QColor(255, 255, 255); hoverTextColor = QColor(250, 250, 250); selectLunarColor = QColor(255, 255, 255); hoverLunarColor = QColor(250, 250, 250); currentBgColor = QColor(255, 255, 255); otherBgColor = QColor(240, 240, 240); selectBgColor = QColor(55,143,250); hoverBgColor = QColor(204, 183, 180); } void LunarCalendarMonthItem::enterEvent(QEvent *) { hover = true; this->update(); } void LunarCalendarMonthItem::leaveEvent(QEvent *) { hover = false; this->update(); } void LunarCalendarMonthItem::mousePressEvent(QMouseEvent *) { pressed = true; this->update(); // Q_EMIT clicked(date, dayType); Q_EMIT monthMessage(date, dayType); } void LunarCalendarMonthItem::mouseReleaseEvent(QMouseEvent *) { pressed = false; this->update(); } void LunarCalendarMonthItem::paintEvent(QPaintEvent *) { QDate dateNow = QDate::currentDate(); //绘制准备工作,启用反锯齿 QPainter painter(this); painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing); //绘制背景和边框 drawBg(&painter); //对比当前的时间,画选中状态 if(dateNow.month() == date.month() && dateNow.year() == date.year()) { drawBgCurrent(&painter, selectBgColor); } //绘制悬停状态 if (hover) { drawBgHover(&painter, hoverBgColor); } //绘制选中状态 if (select) { drawBgHover(&painter, hoverBgColor); } //绘制日期 drawMonth(&painter); } void LunarCalendarMonthItem::drawBg(QPainter *painter) { painter->save(); //根据当前类型选择对应的颜色 QColor bgColor = currentBgColor; if (dayType == DayType_MonthPre || dayType == DayType_MonthNext) { bgColor = otherBgColor; } painter->restore(); } void LunarCalendarMonthItem::drawBgCurrent(QPainter *painter, const QColor &color) { painter->save(); painter->setPen(Qt::NoPen); painter->setBrush(color); QRect rect = this->rect(); painter->drawRoundedRect(rect,4,4); painter->restore(); } void LunarCalendarMonthItem::drawBgHover(QPainter *painter, const QColor &color) { painter->save(); QRect rect = this->rect(); painter->setPen(QPen(QColor(55,143,250),2)); painter->drawRoundedRect(rect,4,4); painter->restore(); } void LunarCalendarMonthItem::drawMonth(QPainter *painter) { int width = this->width(); int height = this->height(); int side = qMin(width, height); painter->save(); //根据当前类型选择对应的颜色 QColor color = currentTextColor; if (dayType == DayType_MonthPre || dayType == DayType_MonthNext) { color = otherTextColor; } else if (dayType == DayType_WeekEnd) { color = weekColor; } painter->setPen(color); QFont font; font.setPixelSize(side * 0.2); //设置文字粗细 font.setBold(true); painter->setFont(font); QRect dayRect = QRect(0, 0, width, height / 1.7); QString arg = QString::number(date.month()) +"月"; painter->drawText(dayRect, Qt::AlignHCenter | Qt::AlignBottom, arg); painter->restore(); } bool LunarCalendarMonthItem::getSelect() const { return this->select; } bool LunarCalendarMonthItem::getShowLunar() const { return this->showLunar; } QString LunarCalendarMonthItem::getBgImage() const { return this->bgImage; } LunarCalendarMonthItem::SelectType LunarCalendarMonthItem::getSelectType() const { return this->selectType; } QDate LunarCalendarMonthItem::getDate() const { return this->date; } QString LunarCalendarMonthItem::getLunar() const { return this->lunar; } LunarCalendarMonthItem::DayType LunarCalendarMonthItem::getDayType() const { return this->dayType; } QColor LunarCalendarMonthItem::getBorderColor() const { return this->borderColor; } QColor LunarCalendarMonthItem::getWeekColor() const { return this->weekColor; } QColor LunarCalendarMonthItem::getSuperColor() const { return this->superColor; } QColor LunarCalendarMonthItem::getLunarColor() const { return this->lunarColor; } QColor LunarCalendarMonthItem::getCurrentTextColor() const { return this->currentTextColor; } QColor LunarCalendarMonthItem::getOtherTextColor() const { return this->otherTextColor; } QColor LunarCalendarMonthItem::getSelectTextColor() const { return this->selectTextColor; } QColor LunarCalendarMonthItem::getHoverTextColor() const { return this->hoverTextColor; } QColor LunarCalendarMonthItem::getCurrentLunarColor() const { return this->currentLunarColor; } QColor LunarCalendarMonthItem::getOtherLunarColor() const { return this->otherLunarColor; } QColor LunarCalendarMonthItem::getSelectLunarColor() const { return this->selectLunarColor; } QColor LunarCalendarMonthItem::getHoverLunarColor() const { return this->hoverLunarColor; } QColor LunarCalendarMonthItem::getCurrentBgColor() const { return this->currentBgColor; } QColor LunarCalendarMonthItem::getOtherBgColor() const { return this->otherBgColor; } QColor LunarCalendarMonthItem::getSelectBgColor() const { return this->selectBgColor; } QColor LunarCalendarMonthItem::getHoverBgColor() const { return this->hoverBgColor; } QSize LunarCalendarMonthItem::sizeHint() const { return QSize(100, 100); } QSize LunarCalendarMonthItem::minimumSizeHint() const { return QSize(20, 20); } void LunarCalendarMonthItem::setSelect(bool select) { if (this->select != select) { this->select = select; this->update(); } } void LunarCalendarMonthItem::setShowLunar(bool showLunar) { this->showLunar = showLunar; this->update(); } void LunarCalendarMonthItem::setBgImage(const QString &bgImage) { if (this->bgImage != bgImage) { this->bgImage = bgImage; this->update(); } } void LunarCalendarMonthItem::setSelectType(const LunarCalendarMonthItem::SelectType &selectType) { if (this->selectType != selectType) { this->selectType = selectType; this->update(); } } void LunarCalendarMonthItem::setDate(const QDate &date) { if (this->date != date) { this->date = date; this->update(); } } void LunarCalendarMonthItem::setLunar(const QString &lunar) { if (this->lunar != lunar) { this->lunar = lunar; this->update(); } } void LunarCalendarMonthItem::setDayType(const LunarCalendarMonthItem::DayType &dayType) { if (this->dayType != dayType) { this->dayType = dayType; this->update(); } } void LunarCalendarMonthItem::setDate(const QDate &date, const QString &lunar, const DayType &dayType) { this->date = date; this->lunar = lunar; this->dayType = dayType; this->update(); } void LunarCalendarMonthItem::setBorderColor(const QColor &borderColor) { if (this->borderColor != borderColor) { this->borderColor = borderColor; this->update(); } } void LunarCalendarMonthItem::setWeekColor(const QColor &weekColor) { if (this->weekColor != weekColor) { this->weekColor = weekColor; this->update(); } } void LunarCalendarMonthItem::setSuperColor(const QColor &superColor) { if (this->superColor != superColor) { this->superColor = superColor; this->update(); } } void LunarCalendarMonthItem::setLunarColor(const QColor &lunarColor) { if (this->lunarColor != lunarColor) { this->lunarColor = lunarColor; this->update(); } } void LunarCalendarMonthItem::setCurrentTextColor(const QColor ¤tTextColor) { if (this->currentTextColor != currentTextColor) { this->currentTextColor = currentTextColor; this->update(); } } void LunarCalendarMonthItem::setOtherTextColor(const QColor &otherTextColor) { if (this->otherTextColor != otherTextColor) { this->otherTextColor = otherTextColor; this->update(); } } void LunarCalendarMonthItem::setSelectTextColor(const QColor &selectTextColor) { if (this->selectTextColor != selectTextColor) { this->selectTextColor = selectTextColor; this->update(); } } void LunarCalendarMonthItem::setHoverTextColor(const QColor &hoverTextColor) { if (this->hoverTextColor != hoverTextColor) { this->hoverTextColor = hoverTextColor; this->update(); } } void LunarCalendarMonthItem::setCurrentLunarColor(const QColor ¤tLunarColor) { if (this->currentLunarColor != currentLunarColor) { this->currentLunarColor = currentLunarColor; this->update(); } } void LunarCalendarMonthItem::setOtherLunarColor(const QColor &otherLunarColor) { if (this->otherLunarColor != otherLunarColor) { this->otherLunarColor = otherLunarColor; this->update(); } } ukui-panel-3.0.6.4/ukui-calendar/lunarcalendarwidget/lunarcalendaryearitem.h0000644000175000017500000001736414203402514025651 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #ifdef quc #if (QT_VERSION < QT_VERSION_CHECK(5,7,0)) #include #else #include #endif class QDESIGNER_WIDGET_EXPORT LunarCalendarItem : public QWidget #else class LunarCalendarYearItem : public QWidget #endif { Q_OBJECT Q_ENUMS(DayType) Q_ENUMS(SelectType) Q_PROPERTY(bool select READ getSelect WRITE setSelect) Q_PROPERTY(bool showLunar READ getShowLunar WRITE setShowLunar) Q_PROPERTY(QString bgImage READ getBgImage WRITE setBgImage) Q_PROPERTY(SelectType selectType READ getSelectType WRITE setSelectType) Q_PROPERTY(QDate date READ getDate WRITE setDate) Q_PROPERTY(QString lunar READ getLunar WRITE setLunar) Q_PROPERTY(DayType dayType READ getDayType WRITE setDayType) Q_PROPERTY(QColor borderColor READ getBorderColor WRITE setBorderColor) Q_PROPERTY(QColor weekColor READ getWeekColor WRITE setWeekColor) Q_PROPERTY(QColor superColor READ getSuperColor WRITE setSuperColor) Q_PROPERTY(QColor lunarColor READ getLunarColor WRITE setLunarColor) Q_PROPERTY(QColor currentTextColor READ getCurrentTextColor WRITE setCurrentTextColor) Q_PROPERTY(QColor otherTextColor READ getOtherTextColor WRITE setOtherTextColor) Q_PROPERTY(QColor selectTextColor READ getSelectTextColor WRITE setSelectTextColor) Q_PROPERTY(QColor hoverTextColor READ getHoverTextColor WRITE setHoverTextColor) Q_PROPERTY(QColor currentLunarColor READ getCurrentLunarColor WRITE setCurrentLunarColor) Q_PROPERTY(QColor otherLunarColor READ getOtherLunarColor WRITE setOtherLunarColor) public: enum DayType { DayType_MonthPre = 0, //上月剩余天数 DayType_MonthNext = 1, //下个月的天数 DayType_MonthCurrent = 2, //当月天数 DayType_WeekEnd = 3 //周末 }; enum SelectType { SelectType_Rect = 0, //矩形背景 SelectType_Circle = 1, //圆形背景 SelectType_Triangle = 2, //带三角标 SelectType_Image = 3 //图片背景 }; explicit LunarCalendarYearItem(QWidget *parent = 0); QMap> worktime; protected: void enterEvent(QEvent *); void leaveEvent(QEvent *); void mousePressEvent(QMouseEvent *); void mouseReleaseEvent(QMouseEvent *); void paintEvent(QPaintEvent *); void drawBg(QPainter *painter); void drawBgCurrent(QPainter *painter, const QColor &color); void drawBgHover(QPainter *painter, const QColor &color); void drawYear(QPainter *painter); private: bool hover; //鼠标是否悬停 bool pressed; //鼠标是否按下 bool select; //是否选中 bool showLunar; //显示农历 QString bgImage; //背景图片 SelectType selectType; //选中模式 QDate date; //当前日期 QString lunar; //农历信息 DayType dayType; //当前日类型 QColor borderColor; //边框颜色 QColor weekColor; //周末颜色 QColor superColor; //角标颜色 QColor lunarColor; //农历节日颜色 QColor currentTextColor; //当前月文字颜色 QColor otherTextColor; //其他月文字颜色 QColor selectTextColor; //选中日期文字颜色 QColor hoverTextColor; //悬停日期文字颜色 QColor currentLunarColor; //当前月农历文字颜色 QColor otherLunarColor; //其他月农历文字颜色 QColor selectLunarColor; //选中日期农历文字颜色 QColor hoverLunarColor; //悬停日期农历文字颜色 QColor currentBgColor; //当前月背景颜色 QColor otherBgColor; //其他月背景颜色 QColor selectBgColor; //选中日期背景颜色 QColor hoverBgColor; //悬停日期背景颜色 public: bool getSelect() const; bool getShowLunar() const; QString getBgImage() const; SelectType getSelectType() const; QDate getDate() const; QString getLunar() const; DayType getDayType() const; QColor getBorderColor() const; QColor getWeekColor() const; QColor getSuperColor() const; QColor getLunarColor() const; QColor getCurrentTextColor() const; QColor getOtherTextColor() const; QColor getSelectTextColor() const; QColor getHoverTextColor() const; QColor getCurrentLunarColor() const; QColor getOtherLunarColor() const; QColor getSelectLunarColor() const; QColor getHoverLunarColor() const; QColor getCurrentBgColor() const; QColor getOtherBgColor() const; QColor getSelectBgColor() const; QColor getHoverBgColor() const; QSize sizeHint() const; QSize minimumSizeHint() const; public Q_SLOTS: //设置是否选中 void setSelect(bool select); //设置是否显示农历信息 void setShowLunar(bool showLunar); //设置背景图片 void setBgImage(const QString &bgImage); //设置选中背景样式 void setSelectType(const SelectType &selectType); //设置日期 void setDate(const QDate &date); //设置农历 void setLunar(const QString &lunar); //设置类型 void setDayType(const DayType &dayType); //设置日期/农历/类型 void setDate(const QDate &date, const QString &lunar, const DayType &dayType); //设置边框颜色 void setBorderColor(const QColor &borderColor); //设置周末颜色 void setWeekColor(const QColor &weekColor); //设置角标颜色 void setSuperColor(const QColor &superColor); //设置农历节日颜色 void setLunarColor(const QColor &lunarColor); //设置当前月文字颜色 void setCurrentTextColor(const QColor ¤tTextColor); //设置其他月文字颜色 void setOtherTextColor(const QColor &otherTextColor); //设置选中日期文字颜色 void setSelectTextColor(const QColor &selectTextColor); //设置悬停日期文字颜色 void setHoverTextColor(const QColor &hoverTextColor); //设置当前月农历文字颜色 void setCurrentLunarColor(const QColor ¤tLunarColor); //设置其他月农历文字颜色 void setOtherLunarColor(const QColor &otherLunarColor); Q_SIGNALS: void clicked(const QDate &date, const LunarCalendarYearItem::DayType &dayType); void yearMessage(const QDate &date, const LunarCalendarYearItem::DayType &dayType); }; #endif // LUNARCALENDARITEM_H ukui-panel-3.0.6.4/ukui-calendar/lunarcalendarwidget/lunarcalendarwidget.h0000644000175000017500000003163714203402514025314 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include #include #include "qfontdatabase.h" #include "qdatetime.h" #include "qlayout.h" #include "qlabel.h" #include "qpushbutton.h" #include "qtoolbutton.h" #include "qcombobox.h" #include "qdebug.h" #include #include #include #include "picturetowhite.h" #include #include #include #include #include #include #include "../../panel/pluginsettings.h" #include "../../panel/iukuipanelplugin.h" #include "lunarcalendarinfo.h" #include "lunarcalendaritem.h" #include "lunarcalendaryearitem.h" #include "lunarcalendarmonthitem.h" #include "customstylePushbutton.h" #include class QLabel; class statelabel; class QComboBox; class LunarCalendarYearItem; class LunarCalendarMonthItem; class LunarCalendarItem; class m_PartLineWidget; #ifdef quc #if (QT_VERSION < QT_VERSION_CHECK(5,7,0)) #include #else #include #endif class QDESIGNER_WIDGET_EXPORT LunarCalendarWidget : public QWidget #else class LunarCalendarWidget : public QWidget #endif { Q_OBJECT Q_ENUMS(CalendarStyle) Q_ENUMS(WeekNameFormat) Q_ENUMS(SelectType) Q_PROPERTY(CalendarStyle calendarStyle READ getCalendarStyle WRITE setCalendarStyle) Q_PROPERTY(QDate date READ getDate WRITE setDate) Q_PROPERTY(QColor weekTextColor READ getWeekTextColor WRITE setWeekTextColor) Q_PROPERTY(QColor weekBgColor READ getWeekBgColor WRITE setWeekBgColor) Q_PROPERTY(bool showLunar READ getShowLunar WRITE setShowLunar) Q_PROPERTY(QString bgImage READ getBgImage WRITE setBgImage) Q_PROPERTY(SelectType selectType READ getSelectType WRITE setSelectType) Q_PROPERTY(QColor borderColor READ getBorderColor WRITE setBorderColor) Q_PROPERTY(QColor weekColor READ getWeekColor WRITE setWeekColor) Q_PROPERTY(QColor superColor READ getSuperColor WRITE setSuperColor) Q_PROPERTY(QColor lunarColor READ getLunarColor WRITE setLunarColor) Q_PROPERTY(QColor currentTextColor READ getCurrentTextColor WRITE setCurrentTextColor) Q_PROPERTY(QColor otherTextColor READ getOtherTextColor WRITE setOtherTextColor) Q_PROPERTY(QColor selectTextColor READ getSelectTextColor WRITE setSelectTextColor) Q_PROPERTY(QColor hoverTextColor READ getHoverTextColor WRITE setHoverTextColor) Q_PROPERTY(QColor currentLunarColor READ getCurrentLunarColor WRITE setCurrentLunarColor) Q_PROPERTY(QColor otherLunarColor READ getOtherLunarColor WRITE setOtherLunarColor) Q_PROPERTY(QColor selectLunarColor READ getSelectLunarColor WRITE setSelectLunarColor) Q_PROPERTY(QColor hoverLunarColor READ getHoverLunarColor WRITE setHoverLunarColor) Q_PROPERTY(QColor currentBgColor READ getCurrentBgColor WRITE setCurrentBgColor) Q_PROPERTY(QColor otherBgColor READ getOtherBgColor WRITE setOtherBgColor) Q_PROPERTY(QColor selectBgColor READ getSelectBgColor WRITE setSelectBgColor) Q_PROPERTY(QColor hoverBgColor READ getHoverBgColor WRITE setHoverBgColor) public: enum CalendarStyle { CalendarStyle_Red = 0 }; enum WeekNameFormat { WeekNameFormat_Short = 0, //短名称 WeekNameFormat_Normal = 1, //普通名称 WeekNameFormat_Long = 2, //长名称 WeekNameFormat_En = 3 //英文名称 }; enum SelectType { SelectType_Rect = 0, //矩形背景 SelectType_Circle = 1, //圆形背景 SelectType_Triangle = 2, //带三角标 SelectType_Image = 3 //图片背景 }; explicit LunarCalendarWidget(QWidget *parent = 0); ~LunarCalendarWidget(); private: QLabel *datelabel; QLabel *timelabel; QLabel *lunarlabel; QTimer *timer; QVBoxLayout *timeShow; QWidget *widgetTime; QPushButton *btnYear; QPushButton *btnMonth; QPushButton *btnToday; QWidget *labWidget; QLabel *labBottom; QHBoxLayout *labLayout; m_PartLineWidget *lineUp; m_PartLineWidget *lineDown; statelabel *btnPrevYear; statelabel *btnNextYear; QLabel *yijichooseLabel; QCheckBox *yijichoose; QVBoxLayout *yijiLayout; QWidget *yijiWidget; QLabel *yiLabel; QLabel *jiLabel; QWidget *widgetWeek; QWidget *widgetDayBody; QWidget *widgetYearBody; QWidget *widgetmonthBody; QString timemodel = 0; bool yijistate = false; bool lunarstate =false; bool oneRun = true; // IUKUIPanelPlugin *mPlugin; QString dateShowMode; QMap worktimeinside; QMap> worktime; void analysisWorktimeJs(); //解析js文件 void downLabelHandle(const QDate &date); QFont iconFont; //图形字体 bool btnClick; //按钮单击,避开下拉选择重复触发 QComboBox *cboxYearandMonth; //年份下拉框 QLabel *cboxYearandMonthLabel; QList labWeeks; //顶部星期名称 QList dayItems; //日期元素 QList yearItems; //年份元素 QList monthItems; //月份元素 CalendarStyle calendarStyle; //整体样式 bool FirstdayisSun; //首日期为周日 QDate date; //当前日期 QDate clickDate; //保存点击日期 QColor weekTextColor; //星期名称文字颜色 QColor weekBgColor; //星期名称背景色 bool showLunar; //显示农历 QString bgImage; //背景图片 SelectType selectType; //选中模式 QColor borderColor; //边框颜色 QColor weekColor; //周末颜色 QColor superColor; //角标颜色 QColor lunarColor; //农历节日颜色 QColor currentTextColor; //当前月文字颜色 QColor otherTextColor; //其他月文字颜色 QColor selectTextColor; //选中日期文字颜色 QColor hoverTextColor; //悬停日期文字颜色 QColor currentLunarColor; //当前月农历文字颜色 QColor otherLunarColor; //其他月农历文字颜色 QColor selectLunarColor; //选中日期农历文字颜色 QColor hoverLunarColor; //悬停日期农历文字颜色 QColor currentBgColor; //当前月背景颜色 QColor otherBgColor; //其他月背景颜色 QColor selectBgColor; //选中日期背景颜色 QColor hoverBgColor; //悬停日期背景颜色 QGSettings *calendar_gsettings; void setColor(bool mdark_style); void _timeUpdate(); void yijihandle(const QDate &date); QString getSettings(); void setSettings(QString arg); QGSettings *style_settings; bool dark_style; protected : void wheelEvent(QWheelEvent *event); bool eventFilter(QObject *, QEvent *); private Q_SLOTS: void initWidget(); void initStyle(); void initDate(); void changeDate(const QDate &date); void yearChanged(const QString &arg1); void monthChanged(const QString &arg1); void clicked(const QDate &date, const LunarCalendarItem::DayType &dayType); void dayChanged(const QDate &date,const QDate &m_date); void dateChanged(int year, int month, int day); void timerUpdate(); void customButtonsClicked(int x); void yearWidgetChange(); void monthWidgetChange(); public: CalendarStyle getCalendarStyle() const; QDate getDate() const; QColor getWeekTextColor() const; QColor getWeekBgColor() const; bool getShowLunar() const; QString getBgImage() const; SelectType getSelectType() const; QColor getBorderColor() const; QColor getWeekColor() const; QColor getSuperColor() const; QColor getLunarColor() const; QColor getCurrentTextColor() const; QColor getOtherTextColor() const; QColor getSelectTextColor() const; QColor getHoverTextColor() const; QColor getCurrentLunarColor() const; QColor getOtherLunarColor() const; QColor getSelectLunarColor() const; QColor getHoverLunarColor() const; QColor getCurrentBgColor() const; QColor getOtherBgColor() const; QColor getSelectBgColor() const; QColor getHoverBgColor() const; QSize sizeHint() const; QSize minimumSizeHint() const; public Q_SLOTS: void updateYearClicked(const QDate &date, const LunarCalendarYearItem::DayType &dayType); void updateMonthClicked(const QDate &date, const LunarCalendarMonthItem::DayType &dayType); //上一年,下一年 void showPreviousYear(); void showNextYear(); //上一月,下一月 void showPreviousMonth(bool date_clicked = true); void showNextMonth(bool date_clicked = true); //转到今天 void showToday(); //设置整体样式 void setCalendarStyle(const CalendarStyle &calendarStyle); //设置星期名称格式 void setWeekNameFormat(bool FirstDayisSun); //设置日期 void setDate(const QDate &date); //设置顶部星期名称文字颜色+背景色 void setWeekTextColor(const QColor &weekTextColor); void setWeekBgColor(const QColor &weekBgColor); //设置是否显示农历信息 void setShowLunar(bool showLunar); //设置背景图片 void setBgImage(const QString &bgImage); //设置选中背景样式 void setSelectType(const SelectType &selectType); //设置边框颜色 void setBorderColor(const QColor &borderColor); //设置周末颜色 void setWeekColor(const QColor &weekColor); //设置角标颜色 void setSuperColor(const QColor &superColor); //设置农历节日颜色 void setLunarColor(const QColor &lunarColor); //设置当前月文字颜色 void setCurrentTextColor(const QColor ¤tTextColor); //设置其他月文字颜色 void setOtherTextColor(const QColor &otherTextColor); //设置选中日期文字颜色 void setSelectTextColor(const QColor &selectTextColor); //设置悬停日期文字颜色 void setHoverTextColor(const QColor &hoverTextColor); //设置当前月农历文字颜色 void setCurrentLunarColor(const QColor ¤tLunarColor); //设置其他月农历文字颜色 void setOtherLunarColor(const QColor &otherLunarColor); //设置选中日期农历文字颜色 void setSelectLunarColor(const QColor &selectLunarColor); //设置悬停日期农历文字颜色 void setHoverLunarColor(const QColor &hoverLunarColor); //设置当前月背景颜色 void setCurrentBgColor(const QColor ¤tBgColor); //设置其他月背景颜色 void setOtherBgColor(const QColor &otherBgColor); //设置选中日期背景颜色 void setSelectBgColor(const QColor &selectBgColor); //设置悬停日期背景颜色 void setHoverBgColor(const QColor &hoverBgColor); Q_SIGNALS: void clicked(const QDate &date); void selectionChanged(); void yijiChangeUp(); void yijiChangeDown(); }; class m_PartLineWidget : public QWidget { Q_OBJECT public: explicit m_PartLineWidget(QWidget *parent = nullptr); void paintEvent(QPaintEvent *event); }; class statelabel : public QLabel { Q_OBJECT public: statelabel(); protected: void mousePressEvent(QMouseEvent *event); Q_SIGNALS : void labelclick(); }; #endif // LUNARCALENDARWIDGET_H ukui-panel-3.0.6.4/ukui-calendar/lunarcalendarwidget/lunarcalendarinfo.cpp0000644000175000017500000011737314203402514025321 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #define year_2099 QScopedPointer LunarCalendarInfo::self; LunarCalendarInfo *LunarCalendarInfo::Instance() { if (self.isNull()) { static QMutex mutex; QMutexLocker locker(&mutex); if (self.isNull()) { self.reset(new LunarCalendarInfo); } } return self.data(); } LunarCalendarInfo::LunarCalendarInfo(QObject *parent) : QObject(parent) { //农历查表 lunarCalendarTable << 0x04AE53 << 0x0A5748 << 0x5526BD << 0x0D2650 << 0x0D9544 << 0x46AAB9 << 0x056A4D << 0x09AD42 << 0x24AEB6 << 0x04AE4A; //1901-1910 lunarCalendarTable << 0x6A4DBE << 0x0A4D52 << 0x0D2546 << 0x5D52BA << 0x0B544E << 0x0D6A43 << 0x296D37 << 0x095B4B << 0x749BC1 << 0x049754; //1911-1920 lunarCalendarTable << 0x0A4B48 << 0x5B25BC << 0x06A550 << 0x06D445 << 0x4ADAB8 << 0x02B64D << 0x095742 << 0x2497B7 << 0x04974A << 0x664B3E; //1921-1930 lunarCalendarTable << 0x0D4A51 << 0x0EA546 << 0x56D4BA << 0x05AD4E << 0x02B644 << 0x393738 << 0x092E4B << 0x7C96BF << 0x0C9553 << 0x0D4A48; //1931-1940 lunarCalendarTable << 0x6DA53B << 0x0B554F << 0x056A45 << 0x4AADB9 << 0x025D4D << 0x092D42 << 0x2C95B6 << 0x0A954A << 0x7B4ABD << 0x06CA51; //1941-1950 lunarCalendarTable << 0x0B5546 << 0x555ABB << 0x04DA4E << 0x0A5B43 << 0x352BB8 << 0x052B4C << 0x8A953F << 0x0E9552 << 0x06AA48 << 0x6AD53C; //1951-1960 lunarCalendarTable << 0x0AB54F << 0x04B645 << 0x4A5739 << 0x0A574D << 0x052642 << 0x3E9335 << 0x0D9549 << 0x75AABE << 0x056A51 << 0x096D46; //1961-1970 lunarCalendarTable << 0x54AEBB << 0x04AD4F << 0x0A4D43 << 0x4D26B7 << 0x0D254B << 0x8D52BF << 0x0B5452 << 0x0B6A47 << 0x696D3C << 0x095B50; //1971-1980 lunarCalendarTable << 0x049B45 << 0x4A4BB9 << 0x0A4B4D << 0xAB25C2 << 0x06A554 << 0x06D449 << 0x6ADA3D << 0x0AB651 << 0x093746 << 0x5497BB; //1981-1990 lunarCalendarTable << 0x04974F << 0x064B44 << 0x36A537 << 0x0EA54A << 0x86B2BF << 0x05AC53 << 0x0AB647 << 0x5936BC << 0x092E50 << 0x0C9645; //1991-2000 lunarCalendarTable << 0x4D4AB8 << 0x0D4A4C << 0x0DA541 << 0x25AAB6 << 0x056A49 << 0x7AADBD << 0x025D52 << 0x092D47 << 0x5C95BA << 0x0A954E; //2001-2010 lunarCalendarTable << 0x0B4A43 << 0x4B5537 << 0x0AD54A << 0x955ABF << 0x04BA53 << 0x0A5B48 << 0x652BBC << 0x052B50 << 0x0A9345 << 0x474AB9; //2011-2020 lunarCalendarTable << 0x06AA4C << 0x0AD541 << 0x24DAB6 << 0x04B64A << 0x69573D << 0x0A4E51 << 0x0D2646 << 0x5E933A << 0x0D534D << 0x05AA43; //2021-2030 lunarCalendarTable << 0x36B537 << 0x096D4B << 0xB4AEBF << 0x04AD53 << 0x0A4D48 << 0x6D25BC << 0x0D254F << 0x0D5244 << 0x5DAA38 << 0x0B5A4C; //2031-2040 lunarCalendarTable << 0x056D41 << 0x24ADB6 << 0x049B4A << 0x7A4BBE << 0x0A4B51 << 0x0AA546 << 0x5B52BA << 0x06D24E << 0x0ADA42 << 0x355B37; //2041-2050 lunarCalendarTable << 0x09374B << 0x8497C1 << 0x049753 << 0x064B48 << 0x66A53C << 0x0EA54F << 0x06B244 << 0x4AB638 << 0x0AAE4C << 0x092E42; //2051-2060 lunarCalendarTable << 0x3C9735 << 0x0C9649 << 0x7D4ABD << 0x0D4A51 << 0x0DA545 << 0x55AABA << 0x056A4E << 0x0A6D43 << 0x452EB7 << 0x052D4B; //2061-2070 lunarCalendarTable << 0x8A95BF << 0x0A9553 << 0x0B4A47 << 0x6B553B << 0x0AD54F << 0x055A45 << 0x4A5D38 << 0x0A5B4C << 0x052B42 << 0x3A93B6; //2071-2080 lunarCalendarTable << 0x069349 << 0x7729BD << 0x06AA51 << 0x0AD546 << 0x54DABA << 0x04B64E << 0x0A5743 << 0x452738 << 0x0D264A << 0x8E933E; //2081-2090 lunarCalendarTable << 0x0D5252 << 0x0DAA47 << 0x66B53B << 0x056D4F << 0x04AE45 << 0x4A4EB9 << 0x0A4D4C << 0x0D1541 << 0x2D92B5; //2091-2099 //每年春节对应的公历日期 springFestival << 130 << 217 << 206; // 1968 1969 1970 springFestival << 127 << 215 << 203 << 123 << 211 << 131 << 218 << 207 << 128 << 216; // 1971--1980 springFestival << 205 << 125 << 213 << 202 << 220 << 209 << 219 << 217 << 206 << 127; // 1981--1990 springFestival << 215 << 204 << 123 << 210 << 131 << 219 << 207 << 128 << 216 << 205; // 1991--2000 springFestival << 124 << 212 << 201 << 122 << 209 << 129 << 218 << 207 << 126 << 214; // 2001--2010 springFestival << 203 << 123 << 210 << 131 << 219 << 208 << 128 << 216 << 205 << 125; // 2011--2020 springFestival << 212 << 201 << 122 << 210 << 129 << 217 << 206 << 126 << 213 << 203; // 2021--2030 springFestival << 123 << 211 << 131 << 219 << 208 << 128 << 215 << 204 << 124 << 212; // 2031--2040 //16--18位表示闰几月 0--12位表示农历每月的数据 高位表示1月 低位表示12月(农历闰月就会多一个月) lunarData << 461653 << 1386 << 2413; // 1968 1969 1970 lunarData << 330077 << 1197 << 2637 << 268877 << 3365 << 531109 << 2900 << 2922 << 398042 << 2395; // 1971--1980 lunarData << 1179 << 267415 << 2635 << 661067 << 1701 << 1748 << 398772 << 2742 << 2391 << 330031; // 1981--1990 lunarData << 1175 << 1611 << 200010 << 3749 << 527717 << 1452 << 2742 << 332397 << 2350 << 3222; // 1991--2000 lunarData << 268949 << 3402 << 3493 << 133973 << 1386 << 464219 << 605 << 2349 << 334123 << 2709; // 2001--2010 lunarData << 2890 << 267946 << 2773 << 592565 << 1210 << 2651 << 395863 << 1323 << 2707 << 265877; // 2011--2020 lunarData << 1706 << 2773 << 133557 << 1206 << 398510 << 2638 << 3366 << 335142 << 3411 << 1450; // 2021--2030 lunarData << 200042 << 2413 << 723293 << 1197 << 2637 << 399947 << 3365 << 3410 << 334676 << 2906; // 2031--2040 //二十四节气表 chineseTwentyFourData << 0x95 << 0xB4 << 0x96 << 0xA5 << 0x96 << 0x97 << 0x88 << 0x78 << 0x78 << 0x69 << 0x78 << 0x87; // 1970 chineseTwentyFourData << 0x96 << 0xB4 << 0x96 << 0xA6 << 0x97 << 0x97 << 0x78 << 0x79 << 0x79 << 0x69 << 0x78 << 0x77; // 1971 chineseTwentyFourData << 0x96 << 0xA4 << 0xA5 << 0xA5 << 0xA6 << 0xA6 << 0x88 << 0x88 << 0x88 << 0x78 << 0x87 << 0x87; // 1972 chineseTwentyFourData << 0xA5 << 0xB5 << 0x96 << 0xA5 << 0xA6 << 0x96 << 0x88 << 0x78 << 0x78 << 0x78 << 0x87 << 0x87; // 1973 chineseTwentyFourData << 0x95 << 0xB4 << 0x96 << 0xA5 << 0x96 << 0x97 << 0x88 << 0x78 << 0x78 << 0x69 << 0x78 << 0x87; // 1974 chineseTwentyFourData << 0x96 << 0xB4 << 0x96 << 0xA6 << 0x97 << 0x97 << 0x78 << 0x79 << 0x78 << 0x69 << 0x78 << 0x77; // 1975 chineseTwentyFourData << 0x96 << 0xA4 << 0xA5 << 0xB5 << 0xA6 << 0xA6 << 0x88 << 0x89 << 0x88 << 0x78 << 0x87 << 0x87; // 1976 chineseTwentyFourData << 0xA5 << 0xB4 << 0x96 << 0xA5 << 0x96 << 0x96 << 0x88 << 0x88 << 0x78 << 0x78 << 0x87 << 0x87; // 1977 chineseTwentyFourData << 0x95 << 0xB4 << 0x96 << 0xA5 << 0x96 << 0x97 << 0x88 << 0x78 << 0x78 << 0x79 << 0x78 << 0x87; // 1978 chineseTwentyFourData << 0x96 << 0xB4 << 0x96 << 0xA6 << 0x96 << 0x97 << 0x78 << 0x79 << 0x78 << 0x69 << 0x78 << 0x77; // 1979 chineseTwentyFourData << 0x96 << 0xA4 << 0xA5 << 0xB5 << 0xA6 << 0xA6 << 0x88 << 0x88 << 0x88 << 0x78 << 0x87 << 0x87; // 1980 chineseTwentyFourData << 0xA5 << 0xB4 << 0x96 << 0xA5 << 0xA6 << 0x96 << 0x88 << 0x88 << 0x78 << 0x78 << 0x77 << 0x87; // 1981 chineseTwentyFourData << 0x95 << 0xB4 << 0x96 << 0xA5 << 0x96 << 0x97 << 0x88 << 0x78 << 0x78 << 0x79 << 0x77 << 0x87; // 1982 chineseTwentyFourData << 0x95 << 0xB4 << 0x96 << 0xA5 << 0x96 << 0x97 << 0x78 << 0x79 << 0x78 << 0x69 << 0x78 << 0x77; // 1983 chineseTwentyFourData << 0x96 << 0xB4 << 0xA5 << 0xB5 << 0xA6 << 0xA6 << 0x87 << 0x88 << 0x88 << 0x78 << 0x87 << 0x87; // 1984 chineseTwentyFourData << 0xA5 << 0xB4 << 0xA6 << 0xA5 << 0xA6 << 0x96 << 0x88 << 0x88 << 0x78 << 0x78 << 0x87 << 0x87; // 1985 chineseTwentyFourData << 0xA5 << 0xB4 << 0x96 << 0xA5 << 0x96 << 0x97 << 0x88 << 0x78 << 0x78 << 0x79 << 0x77 << 0x87; // 1986 chineseTwentyFourData << 0x95 << 0xB4 << 0x96 << 0xA5 << 0x96 << 0x97 << 0x88 << 0x79 << 0x78 << 0x69 << 0x78 << 0x87; // 1987 chineseTwentyFourData << 0x96 << 0xB4 << 0xA5 << 0xB5 << 0xA6 << 0xA6 << 0x87 << 0x88 << 0x88 << 0x78 << 0x87 << 0x86; // 1988 chineseTwentyFourData << 0xA5 << 0xB4 << 0xA5 << 0xA5 << 0xA6 << 0x96 << 0x88 << 0x88 << 0x88 << 0x78 << 0x87 << 0x87; // 1989 chineseTwentyFourData << 0xA5 << 0xB4 << 0x96 << 0xA5 << 0x96 << 0x96 << 0x88 << 0x78 << 0x78 << 0x79 << 0x77 << 0x87; // 1990 chineseTwentyFourData << 0x95 << 0xB4 << 0x96 << 0xA5 << 0x86 << 0x97 << 0x88 << 0x78 << 0x78 << 0x69 << 0x78 << 0x87; // 1991 chineseTwentyFourData << 0x96 << 0xB4 << 0xA5 << 0xB5 << 0xA6 << 0xA6 << 0x87 << 0x88 << 0x88 << 0x78 << 0x87 << 0x86; // 1992 chineseTwentyFourData << 0xA5 << 0xB3 << 0xA5 << 0xA5 << 0xA6 << 0x96 << 0x88 << 0x88 << 0x88 << 0x78 << 0x87 << 0x87; // 1993 chineseTwentyFourData << 0xA5 << 0xB4 << 0x96 << 0xA5 << 0x96 << 0x96 << 0x88 << 0x78 << 0x78 << 0x78 << 0x87 << 0x87; // 1994 chineseTwentyFourData << 0x95 << 0xB4 << 0x96 << 0xA5 << 0x96 << 0x97 << 0x88 << 0x76 << 0x78 << 0x69 << 0x78 << 0x87; // 1995 chineseTwentyFourData << 0x96 << 0xB4 << 0xA5 << 0xB5 << 0xA6 << 0xA6 << 0x87 << 0x88 << 0x88 << 0x78 << 0x87 << 0x86; // 1996 chineseTwentyFourData << 0xA5 << 0xB3 << 0xA5 << 0xA5 << 0xA6 << 0xA6 << 0x88 << 0x88 << 0x88 << 0x78 << 0x87 << 0x87; // 1997 chineseTwentyFourData << 0xA5 << 0xB4 << 0x96 << 0xA5 << 0x96 << 0x96 << 0x88 << 0x78 << 0x78 << 0x78 << 0x87 << 0x87; // 1998 chineseTwentyFourData << 0x95 << 0xB4 << 0x96 << 0xA5 << 0x96 << 0x97 << 0x88 << 0x78 << 0x78 << 0x69 << 0x78 << 0x87; // 1999 chineseTwentyFourData << 0x96 << 0xB4 << 0xA5 << 0xB5 << 0xA6 << 0xA6 << 0x87 << 0x88 << 0x88 << 0x78 << 0x87 << 0x86; // 2000 chineseTwentyFourData << 0xA5 << 0xB3 << 0xA5 << 0xA5 << 0xA6 << 0xA6 << 0x88 << 0x88 << 0x88 << 0x78 << 0x87 << 0x87; // 2001 chineseTwentyFourData << 0xA5 << 0xB4 << 0x96 << 0xA5 << 0x96 << 0x96 << 0x88 << 0x78 << 0x78 << 0x78 << 0x87 << 0x87; // 2002 chineseTwentyFourData << 0x95 << 0xB4 << 0x96 << 0xA5 << 0x96 << 0x97 << 0x88 << 0x78 << 0x78 << 0x69 << 0x78 << 0x87; // 2003 chineseTwentyFourData << 0x96 << 0xB4 << 0xA5 << 0xB5 << 0xA6 << 0xA6 << 0x87 << 0x88 << 0x88 << 0x78 << 0x87 << 0x86; // 2004 chineseTwentyFourData << 0xA5 << 0xB3 << 0xA5 << 0xA5 << 0xA6 << 0xA6 << 0x88 << 0x88 << 0x88 << 0x78 << 0x87 << 0x87; // 2005 chineseTwentyFourData << 0xA5 << 0xB4 << 0x96 << 0xA5 << 0xA6 << 0x96 << 0x88 << 0x88 << 0x78 << 0x78 << 0x87 << 0x87; // 2006 chineseTwentyFourData << 0x95 << 0xB4 << 0x96 << 0xA5 << 0x96 << 0x97 << 0x88 << 0x78 << 0x78 << 0x69 << 0x78 << 0x87; // 2007 chineseTwentyFourData << 0x96 << 0xB4 << 0xA5 << 0xB5 << 0xA6 << 0xA6 << 0x87 << 0x88 << 0x87 << 0x78 << 0x87 << 0x86; // 2008 chineseTwentyFourData << 0xA5 << 0xB3 << 0xA5 << 0xB5 << 0xA6 << 0xA6 << 0x88 << 0x88 << 0x88 << 0x78 << 0x87 << 0x87; // 2009 chineseTwentyFourData << 0xA5 << 0xB4 << 0x96 << 0xA5 << 0xA6 << 0x96 << 0x88 << 0x88 << 0x78 << 0x78 << 0x87 << 0x87; // 2010 chineseTwentyFourData << 0x95 << 0xB4 << 0x96 << 0xA5 << 0x96 << 0x97 << 0x88 << 0x78 << 0x78 << 0x79 << 0x78 << 0x87; // 2011 chineseTwentyFourData << 0x96 << 0xB4 << 0xA5 << 0xB5 << 0xA5 << 0xA6 << 0x87 << 0x88 << 0x87 << 0x78 << 0x87 << 0x86; // 2012 chineseTwentyFourData << 0xA5 << 0xB3 << 0xA5 << 0xB5 << 0xA6 << 0xA6 << 0x87 << 0x88 << 0x88 << 0x78 << 0x87 << 0x87; // 2013 chineseTwentyFourData << 0xA5 << 0xB4 << 0x96 << 0xA5 << 0xA6 << 0x96 << 0x88 << 0x88 << 0x78 << 0x78 << 0x87 << 0x87; // 2014 chineseTwentyFourData << 0x95 << 0xB4 << 0x96 << 0xA5 << 0x96 << 0x97 << 0x88 << 0x78 << 0x78 << 0x79 << 0x77 << 0x87; // 2015 chineseTwentyFourData << 0x95 << 0xB4 << 0xA5 << 0xB4 << 0xA5 << 0xA6 << 0x87 << 0x88 << 0x87 << 0x78 << 0x87 << 0x86; // 2016 chineseTwentyFourData << 0xA5 << 0xC3 << 0xA5 << 0xB5 << 0xA6 << 0xA6 << 0x87 << 0x88 << 0x88 << 0x78 << 0x87 << 0x87; // 2017 chineseTwentyFourData << 0xA5 << 0xB4 << 0xA6 << 0xA5 << 0xA6 << 0x96 << 0x88 << 0x88 << 0x78 << 0x78 << 0x87 << 0x87; // 2018 chineseTwentyFourData << 0xA5 << 0xB4 << 0x96 << 0xA5 << 0x96 << 0x96 << 0x88 << 0x78 << 0x78 << 0x79 << 0x77 << 0x87; // 2019 chineseTwentyFourData << 0x95 << 0xB4 << 0xA5 << 0xB4 << 0xA5 << 0xA6 << 0x97 << 0x87 << 0x87 << 0x78 << 0x87 << 0x86; // 2020 chineseTwentyFourData << 0xA5 << 0xC3 << 0xA5 << 0xB5 << 0xA6 << 0xA6 << 0x87 << 0x88 << 0x88 << 0x78 << 0x87 << 0x86; // 2021 chineseTwentyFourData << 0xA5 << 0xB4 << 0xA5 << 0xA5 << 0xA6 << 0x96 << 0x88 << 0x88 << 0x88 << 0x78 << 0x87 << 0x87; // 2022 chineseTwentyFourData << 0xA5 << 0xB4 << 0x96 << 0xA5 << 0x96 << 0x96 << 0x88 << 0x78 << 0x78 << 0x79 << 0x77 << 0x87; // 2023 chineseTwentyFourData << 0x95 << 0xB4 << 0xA5 << 0xB4 << 0xA5 << 0xA6 << 0x97 << 0x87 << 0x87 << 0x78 << 0x87 << 0x96; // 2024 chineseTwentyFourData << 0xA5 << 0xC3 << 0xA5 << 0xB5 << 0xA6 << 0xA6 << 0x87 << 0x88 << 0x88 << 0x78 << 0x87 << 0x86; // 2025 chineseTwentyFourData << 0xA5 << 0xB3 << 0xA5 << 0xA5 << 0xA6 << 0xA6 << 0x88 << 0x88 << 0x88 << 0x78 << 0x87 << 0x87; // 2026 chineseTwentyFourData << 0xA5 << 0xB4 << 0x96 << 0xA5 << 0x96 << 0x96 << 0x88 << 0x78 << 0x78 << 0x78 << 0x87 << 0x87; // 2027 chineseTwentyFourData << 0x95 << 0xB4 << 0xA5 << 0xB4 << 0xA5 << 0xA6 << 0x97 << 0x87 << 0x87 << 0x78 << 0x87 << 0x96; // 2028 chineseTwentyFourData << 0xA5 << 0xC3 << 0xA5 << 0xB5 << 0xA6 << 0xA6 << 0x87 << 0x88 << 0x88 << 0x78 << 0x87 << 0x86; // 2029 chineseTwentyFourData << 0xA5 << 0xB3 << 0xA5 << 0xA5 << 0xA6 << 0xA6 << 0x88 << 0x88 << 0x88 << 0x78 << 0x87 << 0x87; // 2030 chineseTwentyFourData << 0xA5 << 0xB4 << 0x96 << 0xA5 << 0x96 << 0x96 << 0x88 << 0x78 << 0x78 << 0x78 << 0x87 << 0x87; // 2031 chineseTwentyFourData << 0x95 << 0xB4 << 0xA5 << 0xB4 << 0xA5 << 0xA6 << 0x97 << 0x87 << 0x87 << 0x78 << 0x87 << 0x96; // 2032 chineseTwentyFourData << 0xA5 << 0xC3 << 0xA5 << 0xB5 << 0xA6 << 0xA6 << 0x88 << 0x88 << 0x88 << 0x78 << 0x87 << 0x86; // 2033 chineseTwentyFourData << 0xA5 << 0xB3 << 0xA5 << 0xA5 << 0xA6 << 0xA6 << 0x88 << 0x78 << 0x88 << 0x78 << 0x87 << 0x87; // 2034 chineseTwentyFourData << 0xA5 << 0xB4 << 0x96 << 0xA5 << 0xA6 << 0x96 << 0x88 << 0x88 << 0x78 << 0x78 << 0x87 << 0x87; // 2035 chineseTwentyFourData << 0x95 << 0xB4 << 0xA5 << 0xB4 << 0xA5 << 0xA6 << 0x97 << 0x87 << 0x87 << 0x78 << 0x87 << 0x96; // 2036 chineseTwentyFourData << 0xA5 << 0xC3 << 0xA5 << 0xB5 << 0xA6 << 0xA6 << 0x87 << 0x88 << 0x88 << 0x78 << 0x87 << 0x86; // 2037 chineseTwentyFourData << 0xA5 << 0xB3 << 0xA5 << 0xA5 << 0xA6 << 0xA6 << 0x88 << 0x88 << 0x88 << 0x78 << 0x87 << 0x87; // 2038 chineseTwentyFourData << 0xA5 << 0xB4 << 0x96 << 0xA5 << 0xA6 << 0x96 << 0x88 << 0x88 << 0x78 << 0x78 << 0x87 << 0x87; // 2039 chineseTwentyFourData << 0x95 << 0xB4 << 0x96 << 0xA5 << 0x96 << 0x97 << 0x88 << 0x78 << 0x78 << 0x69 << 0x78 << 0x87; // 2040 chineseTwentyFourData << 0xA5 << 0xC3 << 0xA5 << 0xB5 << 0xA5 << 0xA6 << 0x87 << 0x88 << 0x87 << 0x78 << 0x87 << 0x86; // 2041 chineseTwentyFourData << 0xA5 << 0xB3 << 0xA5 << 0xB5 << 0xA6 << 0xA6 << 0x88 << 0x88 << 0x88 << 0x78 << 0x87 << 0x87; // 2042 chineseTwentyFourData << 0xA5 << 0xB4 << 0x96 << 0xA5 << 0xA6 << 0x96 << 0x88 << 0x88 << 0x78 << 0x78 << 0x87 << 0x87; // 2043 chineseTwentyFourData << 0x95 << 0xB4 << 0x96 << 0xA5 << 0x96 << 0x97 << 0x88 << 0x78 << 0x78 << 0x79 << 0x78 << 0x87; // 2044 chineseTwentyFourData << 0xA5 << 0xC3 << 0xA5 << 0xB4 << 0xA5 << 0xA6 << 0x87 << 0x88 << 0x87 << 0x78 << 0x87 << 0x86; // 2045 chineseTwentyFourData << 0xA5 << 0xB3 << 0xA5 << 0xB5 << 0xA6 << 0xA6 << 0x87 << 0x88 << 0x88 << 0x78 << 0x87 << 0x87; // 2046 chineseTwentyFourData << 0xA5 << 0xB4 << 0x96 << 0xA5 << 0xA6 << 0x96 << 0x88 << 0x88 << 0x78 << 0x78 << 0x87 << 0x87; // 2047 chineseTwentyFourData << 0x95 << 0xB4 << 0x96 << 0xA5 << 0x96 << 0x96 << 0x88 << 0x78 << 0x78 << 0x79 << 0x77 << 0x87; // 2048 chineseTwentyFourData << 0xA4 << 0xC3 << 0xA5 << 0xB4 << 0xA5 << 0xA6 << 0x97 << 0x87 << 0x87 << 0x78 << 0x87 << 0x86; // 2049 chineseTwentyFourData << 0xA5 << 0xC3 << 0xA5 << 0xB5 << 0xA6 << 0xA6 << 0x87 << 0x88 << 0x88 << 0x78 << 0x87 << 0x87; // 2050 chineseTwentyFourData << 0xA5 << 0xB4 << 0xA5 << 0xA5 << 0xA6 << 0x96 << 0x88 << 0x88 << 0x88 << 0x78 << 0x87 << 0x87; // 2051 chineseTwentyFourData << 0xA5 << 0xB4 << 0x96 << 0xA5 << 0x96 << 0x96 << 0x88 << 0x78 << 0x78 << 0x79 << 0x77 << 0x87; // 2052 chineseTwentyFourData << 0xA4 << 0xC3 << 0xA5 << 0xB4 << 0xA5 << 0xA6 << 0x97 << 0x87 << 0x87 << 0x78 << 0x87 << 0x86; // 2053 chineseTwentyFourData << 0xA5 << 0xC3 << 0xA5 << 0xB5 << 0xA6 << 0xA6 << 0x87 << 0x88 << 0x88 << 0x78 << 0x87 << 0x87; // 2054 chineseTwentyFourData << 0xA5 << 0xB4 << 0xA5 << 0xA5 << 0xA6 << 0xA6 << 0x88 << 0x88 << 0x88 << 0x78 << 0x87 << 0x87; // 2055 chineseTwentyFourData << 0xA5 << 0xB4 << 0x96 << 0xA5 << 0x96 << 0x96 << 0x88 << 0x78 << 0x78 << 0x79 << 0x77 << 0x87; // 2056 chineseTwentyFourData << 0xA4 << 0xC3 << 0xA5 << 0xB4 << 0xA5 << 0xA6 << 0x97 << 0x87 << 0x87 << 0x78 << 0x87 << 0x96; // 2057 chineseTwentyFourData << 0xA5 << 0xC3 << 0xA5 << 0xB5 << 0xA6 << 0xA6 << 0x87 << 0x88 << 0x88 << 0x78 << 0x87 << 0x86; // 2058 chineseTwentyFourData << 0xA5 << 0xB4 << 0xA5 << 0xA5 << 0xA6 << 0xA6 << 0x88 << 0x88 << 0x88 << 0x78 << 0x87 << 0x87; // 2059 chineseTwentyFourData << 0xA5 << 0xB4 << 0x96 << 0xA5 << 0x96 << 0x96 << 0x88 << 0x78 << 0x78 << 0x78 << 0x87 << 0x87; // 2060 chineseTwentyFourData << 0xA4 << 0xC3 << 0xA5 << 0xB4 << 0xA5 << 0xA6 << 0x97 << 0x87 << 0x87 << 0x78 << 0x87 << 0x96; // 2061 chineseTwentyFourData << 0xA5 << 0xC3 << 0xA5 << 0xB5 << 0xA6 << 0xA6 << 0x87 << 0x88 << 0x88 << 0x78 << 0x87 << 0x86; // 2062 chineseTwentyFourData << 0xA5 << 0xB3 << 0xA5 << 0xA5 << 0xA6 << 0xA6 << 0x88 << 0x88 << 0x88 << 0x78 << 0x87 << 0x87; // 2063 chineseTwentyFourData << 0xA5 << 0xB4 << 0x96 << 0xA5 << 0x96 << 0x96 << 0x88 << 0x78 << 0x78 << 0x78 << 0x87 << 0x87; // 2064 chineseTwentyFourData << 0xA4 << 0xC3 << 0xA5 << 0xB4 << 0xA5 << 0xA6 << 0x97 << 0x87 << 0x87 << 0x78 << 0x87 << 0x96; // 2065 chineseTwentyFourData << 0xA5 << 0xC3 << 0xA5 << 0xB5 << 0xA6 << 0xA6 << 0x87 << 0x88 << 0x88 << 0x78 << 0x87 << 0x86; // 2066 chineseTwentyFourData << 0xA5 << 0xB3 << 0xA5 << 0xA5 << 0xA6 << 0xA6 << 0x88 << 0x88 << 0x88 << 0x78 << 0x87 << 0x87; // 2067 chineseTwentyFourData << 0xA5 << 0xB4 << 0x96 << 0xA5 << 0xA6 << 0x96 << 0x88 << 0x88 << 0x78 << 0x78 << 0x87 << 0x87; // 2068 chineseTwentyFourData << 0xA4 << 0xC3 << 0xA5 << 0xB4 << 0xA5 << 0xA6 << 0x97 << 0x87 << 0x87 << 0x78 << 0x87 << 0x96; // 2069 chineseTwentyFourData << 0xA5 << 0xC3 << 0xA5 << 0xB5 << 0xA5 << 0xA6 << 0x87 << 0x88 << 0x87 << 0x78 << 0x87 << 0x86; // 2070 chineseTwentyFourData << 0xA5 << 0xB3 << 0xA5 << 0xA5 << 0xA6 << 0xA6 << 0x88 << 0x88 << 0x88 << 0x78 << 0x87 << 0x87; // 2071 chineseTwentyFourData << 0xA5 << 0xB4 << 0x96 << 0xA5 << 0xA6 << 0x96 << 0x88 << 0x88 << 0x78 << 0x78 << 0x87 << 0x87; // 2072 chineseTwentyFourData << 0xA4 << 0xC3 << 0xA5 << 0xB4 << 0xA5 << 0xA6 << 0x97 << 0x87 << 0x87 << 0x88 << 0x87 << 0x96; // 2073 chineseTwentyFourData << 0xA5 << 0xC3 << 0xA5 << 0xB5 << 0xA5 << 0xA6 << 0x87 << 0x88 << 0x87 << 0x78 << 0x87 << 0x86; // 2074 chineseTwentyFourData << 0xA5 << 0xB3 << 0xA5 << 0xB5 << 0xA6 << 0xA6 << 0x87 << 0x88 << 0x88 << 0x78 << 0x87 << 0x87; // 2075 chineseTwentyFourData << 0xA5 << 0xB4 << 0x96 << 0xA5 << 0xA6 << 0x96 << 0x88 << 0x88 << 0x78 << 0x78 << 0x87 << 0x87; // 2076 chineseTwentyFourData << 0xA4 << 0xC3 << 0xA5 << 0xB4 << 0xA5 << 0xA6 << 0x97 << 0x87 << 0x87 << 0x88 << 0x87 << 0x96; // 2077 chineseTwentyFourData << 0xA5 << 0xC3 << 0xA5 << 0xB4 << 0xA5 << 0xA6 << 0x97 << 0x88 << 0x87 << 0x78 << 0x87 << 0x86; // 2078 chineseTwentyFourData << 0xA5 << 0xB3 << 0xA5 << 0xB5 << 0xA6 << 0xA6 << 0x87 << 0x88 << 0x88 << 0x78 << 0x87 << 0x87; // 2079 chineseTwentyFourData << 0xA5 << 0xB4 << 0x96 << 0xA5 << 0xA6 << 0x96 << 0x88 << 0x88 << 0x78 << 0x78 << 0x87 << 0x87; // 2080 chineseTwentyFourData << 0xA4 << 0xC3 << 0xA5 << 0xB4 << 0xA5 << 0xA5 << 0x97 << 0x87 << 0x87 << 0x88 << 0x86 << 0x96; // 2081 chineseTwentyFourData << 0xA5 << 0xC3 << 0xA5 << 0xB4 << 0xA5 << 0xA6 << 0x97 << 0x87 << 0x87 << 0x78 << 0x87 << 0x86; // 2082 chineseTwentyFourData << 0xA5 << 0xC3 << 0xA5 << 0xB5 << 0xA6 << 0xA6 << 0x87 << 0x88 << 0x88 << 0x78 << 0x87 << 0x87; // 2083 chineseTwentyFourData << 0xA5 << 0xB4 << 0xA6 << 0xA5 << 0xA6 << 0x96 << 0x88 << 0x88 << 0x88 << 0x78 << 0x87 << 0x87; // 2084 chineseTwentyFourData << 0xB4 << 0xC3 << 0xA5 << 0xB4 << 0xA5 << 0xA5 << 0x97 << 0x87 << 0x87 << 0x88 << 0x86 << 0x96; // 2085 chineseTwentyFourData << 0xA4 << 0xC3 << 0xA5 << 0xB4 << 0xA5 << 0xA6 << 0x97 << 0x87 << 0x87 << 0x78 << 0x87 << 0x86; // 2086 chineseTwentyFourData << 0xA5 << 0xC3 << 0xA5 << 0xB5 << 0xA6 << 0xA6 << 0x87 << 0x88 << 0x88 << 0x78 << 0x87 << 0x87; // 2087 chineseTwentyFourData << 0xA5 << 0xB4 << 0xA5 << 0xA5 << 0xA6 << 0xA6 << 0x88 << 0x88 << 0x88 << 0x78 << 0x87 << 0x87; // 2088 chineseTwentyFourData << 0xB4 << 0xC3 << 0xA5 << 0xB4 << 0xA5 << 0xA5 << 0x97 << 0x87 << 0x87 << 0x88 << 0x96 << 0x96; // 2089 chineseTwentyFourData << 0xA4 << 0xC3 << 0xA5 << 0xB4 << 0xA5 << 0xA6 << 0x97 << 0x87 << 0x87 << 0x78 << 0x87 << 0x96; // 2090 chineseTwentyFourData << 0xA5 << 0xC3 << 0xA5 << 0xB5 << 0xA6 << 0xA6 << 0x87 << 0x88 << 0x88 << 0x78 << 0x87 << 0x86; // 2091 chineseTwentyFourData << 0xA5 << 0xB4 << 0xA5 << 0xA5 << 0xA6 << 0xA6 << 0x88 << 0x88 << 0x88 << 0x78 << 0x87 << 0x87; // 2092 chineseTwentyFourData << 0xB4 << 0xC3 << 0xA5 << 0xB4 << 0xA5 << 0xA5 << 0x97 << 0x87 << 0x87 << 0x87 << 0x96 << 0x96; // 2093 chineseTwentyFourData << 0xA4 << 0xC3 << 0xA5 << 0xB4 << 0xA5 << 0xA6 << 0x97 << 0x87 << 0x87 << 0x78 << 0x87 << 0x96; // 2094 chineseTwentyFourData << 0xA5 << 0xC3 << 0xA5 << 0xB5 << 0xA6 << 0xA6 << 0x87 << 0x88 << 0x88 << 0x78 << 0x87 << 0x86; // 2095 chineseTwentyFourData << 0xA5 << 0xB3 << 0xA5 << 0xA5 << 0xA6 << 0xA6 << 0x88 << 0x88 << 0x88 << 0x78 << 0x87 << 0x87; // 2096 chineseTwentyFourData << 0xB4 << 0xC3 << 0xA5 << 0xB4 << 0xA5 << 0xA5 << 0x97 << 0x97 << 0x87 << 0x87 << 0x96 << 0x96; // 2097 chineseTwentyFourData << 0xA4 << 0xC3 << 0xA5 << 0xB4 << 0xA5 << 0xA6 << 0x97 << 0x87 << 0x87 << 0x78 << 0x87 << 0x96; // 2098 chineseTwentyFourData << 0xA5 << 0xC3 << 0xA5 << 0xB5 << 0xA6 << 0xA6 << 0x87 << 0x88 << 0x88 << 0x78 << 0x87 << 0x86; // 2099 //公历每月前面的天数 monthAdd << 0 << 31 << 59 << 90 << 120 << 151 << 181 << 212 << 243 << 273 << 304 << 334; //农历日期名称 listDayName << "*" << "初一" << "初二" << "初三" << "初四" << "初五" << "初六" << "初七" << "初八" << "初九" << "初十" << "十一" << "十二" << "十三" << "十四" << "十五" << "十六" << "十七" << "十八" << "十九" << "二十" << "廿一" << "廿二" << "廿三" << "廿四" << "廿五" << "廿六" << "廿七" << "廿八" << "廿九" << "三十"; //农历月份名称 listMonthName << "*" << "正月" << "二月" << "三月" << "四月" << "五月" << "六月" << "七月" << "八月" << "九月" << "十月" << "冬月" << "腊月"; //二十四节气名称 listSolarTerm << "小寒" << "大寒" << "立春" << "雨水" << "惊蛰" << "春分" << "清明" << "谷雨" << "立夏" << "小满" << "芒种" << "夏至" << "小暑" << "大暑" << "立秋" << "处暑" << "白露" << "秋分" << "寒露" << "霜降" << "立冬" << "小雪" << "大雪" << "冬至"; //天干 listTianGan << "甲" << "乙" << "丙" << "丁" << "戊" << "己" << "庚" << "辛" << "壬" << "癸"; //地支 listDiZhi << "子" << "丑" << "寅" << "卯" << "辰" << "巳" << "午" << "未" << "申" << "酉" << "戌" << "亥"; //属相 listShuXiang << "鼠" << "牛" << "虎" << "兔" << "龙" << "蛇" << "马" << "羊" << "猴" << "鸡" << "狗" << "猪"; } //计算是否闰年 bool LunarCalendarInfo::isLoopYear(int year) { return (((0 == (year % 4)) && (0 != (year % 100))) || (0 == (year % 400))); } //计算指定年月该月共多少天 int LunarCalendarInfo::getMonthDays(int year, int month) { int countDay = 0; int loopDay = isLoopYear(year) ? 1 : 0; switch (month) { case 1: countDay = 31; break; case 2: countDay = 28 + loopDay; break; case 3: countDay = 31; break; case 4: countDay = 30; break; case 5: countDay = 31; break; case 6: countDay = 30; break; case 7: countDay = 31; break; case 8: countDay = 31; break; case 9: countDay = 30; break; case 10: countDay = 31; break; case 11: countDay = 30; break; case 12: countDay = 31; break; default: countDay = 30; break; } return countDay; } //计算指定年月对应到该月共多少天 int LunarCalendarInfo::getTotalMonthDays(int year, int month) { int countDay = 0; int loopDay = isLoopYear(year) ? 1 : 0; switch (month) { case 1: countDay = 0; break; case 2: countDay = 31; break; case 3: countDay = 59 + loopDay; break; case 4: countDay = 90 + loopDay; break; case 5: countDay = 120 + loopDay; break; case 6: countDay = 151 + loopDay; break; case 7: countDay = 181 + loopDay; break; case 8: countDay = 212 + loopDay; break; case 9: countDay = 243 + loopDay; break; case 10: countDay = 273 + loopDay; break; case 11: countDay = 304 + loopDay; break; case 12: countDay = 334 + loopDay; break; default: countDay = 0; break; } return countDay; } //计算指定年月对应星期几 int LunarCalendarInfo::getFirstDayOfWeek(int year, int month, bool FirstDayisSun) { int week = 0; week = (year + (year - 1) / 4 - (year - 1) / 100 + (year - 1) / 400) % 7; week += getTotalMonthDays(year, month); week = week % 7 - (!FirstDayisSun); if (week == -1) week = 6; return week; } //计算国际节日 QString LunarCalendarInfo::getHoliday(int month, int day) { int temp = (month << 8) | day; QString strHoliday; switch (temp) { case 0x0101: strHoliday = "元旦"; break; case 0x020E: strHoliday = "情人节"; break; case 0x0305: strHoliday = "志愿者"; break; case 0x0308: strHoliday = "妇女节"; break; case 0x030C: strHoliday = "植树节"; break; case 0x0401: strHoliday = "愚人节"; break; case 0x0501: strHoliday = "劳动节"; break; case 0x0504: strHoliday = "青年节"; break; case 0x0601: strHoliday = "儿童节"; break; case 0x0606: strHoliday = "爱眼日"; break; case 0x0701: strHoliday = "建党节"; break; case 0x0707: strHoliday = "抗战日"; break; case 0x0801: strHoliday = "建军节"; break; case 0x090A: strHoliday = "教师节"; break; case 0x0A01: strHoliday = "国庆节"; break; case 0x0B08: strHoliday = "记者节"; break; case 0x0B09: strHoliday = "消防日"; break; case 0x0C18: strHoliday = "平安夜"; break; case 0x0C19: strHoliday = "圣诞节"; break; default: break; } return strHoliday; } //计算二十四节气 QString LunarCalendarInfo::getSolarTerms(int year, int month, int day) { QString strSolarTerms; int dayTemp = 0; int index = (year - 1970) * 12 + month - 1; if (day < 15) { dayTemp = 15 - day; if ((chineseTwentyFourData.at(index) >> 4) == dayTemp) { strSolarTerms = listSolarTerm.at(2 * (month - 1)); } } else if (day > 15) { dayTemp = day - 15; if ((chineseTwentyFourData.at(index) & 0x0f) == dayTemp) { strSolarTerms = listSolarTerm.at(2 * (month - 1) + 1); } } return strSolarTerms; } //计算农历节日(必须传入农历年份月份) QString LunarCalendarInfo::getLunarFestival(int month, int day) { int temp = (month << 8) | day; QString strFestival; switch (temp) { case 0x0201: strFestival = "二月"; break; case 0x0301: strFestival = "三月"; break; case 0x0401: strFestival = "四月"; break; case 0x0501: strFestival = "五月"; break; case 0x0601: strFestival = "六月"; break; case 0x0701: strFestival = "七月"; break; case 0x0801: strFestival = "八月"; break; case 0x0901: strFestival = "九月"; break; case 0x0A01: strFestival = "十月"; break; case 0x0B01: strFestival = "冬月"; break; case 0x0C01: strFestival = "腊月"; break; case 0x0101: strFestival = "春节"; break; case 0x010F: strFestival = "元宵节"; break; case 0x0202: strFestival = "龙抬头"; break; case 0x0505: strFestival = "端午节"; break; case 0x0707: strFestival = "七夕节"; break; case 0x080F: strFestival = "中秋节"; break; case 0x0909: strFestival = "重阳节"; break; case 0x0C08: strFestival = "腊八节"; break; case 0x0C1E: strFestival = "除夕"; break; default: break; } return strFestival; } //计算农历年 天干+地支+生肖 QString LunarCalendarInfo::getLunarYear(int year) { QString strYear; if (year > 1924) { int temp = year - 1924; strYear.append(listTianGan.at(temp % 10)); strYear.append(listDiZhi.at(temp % 12)); strYear.append("年"); strYear.append(listShuXiang.at(temp % 12)); strYear.append("年"); } return strYear; } void LunarCalendarInfo::getLunarCalendarInfo(int year, int month, int day, QString &strHoliday, QString &strSolarTerms, QString &strLunarFestival, QString &strLunarYear, QString &strLunarMonth, QString &strLunarDay) { //过滤不在范围内的年月日 if (year < 1901 || year > 2099 || month < 1 || month > 12 || day < 1 || day > 31) { return; } strHoliday = getHoliday(month, day); strSolarTerms = getSolarTerms(year, month, day); #ifndef year_2099 //现在计算农历:获得当年春节的公历日期(比如:2015年春节日期为(2月19日)) //以此为分界点,2.19前面的农历是2014年农历(用2014年农历数据来计算) //2.19以及之后的日期,农历为2015年农历(用2015年农历数据来计算) int temp, tempYear, tempMonth, isEnd, k, n; tempMonth = year - 1968; int springFestivalMonth = springFestival.at(tempMonth) / 100; int springFestivalDaty = springFestival.at(tempMonth) % 100; if (month < springFestivalMonth) { tempMonth--; tempYear = 365 * 1 + day + monthAdd.at(month - 1) - 31 * ((springFestival.at(tempMonth) / 100) - 1) - springFestival.at(tempMonth) % 100 + 1; if ((!(year % 4)) && (month > 2)) { tempYear = tempYear + 1; } if ((!((year - 1) % 4))) { tempYear = tempYear + 1; } } else if (month == springFestivalMonth) { if (day < springFestivalDaty) { tempMonth--; tempYear = 365 * 1 + day + monthAdd.at(month - 1) - 31 * ((springFestival.at(tempMonth) / 100) - 1) - springFestival.at(tempMonth) % 100 + 1; if ((!(year % 4)) && (month > 2)) { tempYear = tempYear + 1; } if ((!((year - 1) % 4))) { tempYear = tempYear + 1; } } else { tempYear = day + monthAdd.at(month - 1) - 31 * ((springFestival.at(tempMonth) / 100) - 1) - springFestival.at(tempMonth) % 100 + 1; if ((!(year % 4)) && (month > 2)) { tempYear = tempYear + 1; } } } else { tempYear = day + monthAdd.at(month - 1) - 31 * ((springFestival.at(tempMonth) / 100) - 1) - springFestival.at(tempMonth) % 100 + 1; if ((!(year % 4)) && (month > 2)) { tempYear = tempYear + 1; } } //计算农历天干地支月日 isEnd = 0; while (isEnd != 1) { if (lunarData.at(tempMonth) < 4095) { k = 11; } else { k = 12; } n = k; while (n >= 0) { temp = lunarData.at(tempMonth); temp = temp >> n; temp = temp % 2; if (tempYear <= (29 + temp)) { isEnd = 1; break; } tempYear = tempYear - 29 - temp; n = n - 1; } if (isEnd) { break; } tempMonth = tempMonth + 1; } //农历的年月日 year = 1969 + tempMonth - 1; month = k - n + 1; day = tempYear; if (k == 12) { if (month == (lunarData.at(tempMonth) / 65536) + 1) { month = 1 - month; } else if (month > (lunarData.at(tempMonth) / 65536) + 1) { month = month - 1; } } strLunarYear = getLunarYear(year); if (month < 1 && (1 == day)) { month = month * -1; strLunarMonth = "闰" + listMonthName.at(month); } else { strLunarMonth = listMonthName.at(month); } strLunarDay = listDayName.at(day); strLunarFestival = getLunarFestival(month, day); #else //记录春节离当年元旦的天数 int springOffset = 0; //记录阳历日离当年元旦的天数 int newYearOffset = 0; //记录大小月的天数 29或30 int monthCount = 0; if(((lunarCalendarTable.at(year - 1901) & 0x0060) >> 5) == 1) { springOffset = (lunarCalendarTable.at(year - 1901) & 0x001F) - 1; } else { springOffset = (lunarCalendarTable.at(year - 1901) & 0x001F) - 1 + 31; } //如果是不闰年且不是2月份 +1 newYearOffset = monthAdd.at(month - 1) + day - 1; if((!(year % 4)) && (month > 2)) { newYearOffset++; } //记录从哪个月开始来计算 int index = 0; //用来对闰月的特殊处理 int flag = 0; //判断阳历日在春节前还是春节后,计算农历的月/日 if (newYearOffset >= springOffset) { newYearOffset -= springOffset; month = 1; index = 1; flag = 0; if((lunarCalendarTable.at(year - 1901) & (0x80000 >> (index - 1))) == 0) { monthCount = 29; } else { monthCount = 30; } while (newYearOffset >= monthCount) { newYearOffset -= monthCount; index++; if (month == ((lunarCalendarTable.at(year - 1901) & 0xF00000) >> 20) ) { flag = ~flag; if (flag == 0) { month++; } } else { month++; } if ((lunarCalendarTable.at(year - 1901) & (0x80000 >> (index - 1))) == 0) { monthCount = 29; } else { monthCount = 30; } } day = newYearOffset + 1; } else { springOffset -= newYearOffset; year--; month = 12; flag = 0; if (((lunarCalendarTable.at(year - 1901) & 0xF00000) >> 20) == 0) { index = 12; } else { index = 13; } if ((lunarCalendarTable.at(year - 1901) & (0x80000 >> (index - 1))) == 0) { monthCount = 29; } else { monthCount = 30; } while (springOffset > monthCount) { springOffset -= monthCount; index--; if(flag == 0) { month--; } if(month == ((lunarCalendarTable.at(year - 1901) & 0xF00000) >> 20)) { flag = ~flag; } if ((lunarCalendarTable.at(year - 1901) & (0x80000 >> (index - 1))) == 0) { monthCount = 29; } else { monthCount = 30; } } day = monthCount - springOffset + 1; } //计算农历的索引配置 int temp = 0; temp |= day; temp |= (month << 6); //转换农历的年月 month = (temp & 0x3C0) >> 6; day = temp & 0x3F; strLunarYear = getLunarYear(year); if ((month == ((lunarCalendarTable.at(year - 1901) & 0xF00000) >> 20)) && (1 == day)) { strLunarMonth = "闰" + listMonthName.at(month); } else { strLunarMonth = listMonthName.at(month); } strLunarDay = listDayName.at(day); strLunarFestival = getLunarFestival(month, day); #endif } QString LunarCalendarInfo::getLunarInfo(int year, int month, int day, bool yearInfo, bool monthInfo, bool dayInfo) { QString strHoliday, strSolarTerms, strLunarFestival, strLunarYear, strLunarMonth, strLunarDay; LunarCalendarInfo::Instance()->getLunarCalendarInfo(year, month, day, strHoliday, strSolarTerms, strLunarFestival, strLunarYear, strLunarMonth, strLunarDay); //农历节日优先,其次农历节气,然后公历节日,最后才是农历月份名称 if (!strLunarFestival.isEmpty()) { strLunarDay = strLunarFestival; } else if (!strSolarTerms.isEmpty()) { strLunarDay = strSolarTerms; } else if (!strHoliday.isEmpty()) { strLunarDay = strHoliday; } QString info = QString("%1%2%3") .arg(yearInfo ? strLunarYear + "年" : "") .arg(monthInfo ? strLunarMonth : "") .arg(dayInfo ? strLunarDay : ""); return info; } QString LunarCalendarInfo::getLunarYearMonthDay(int year, int month, int day) { return getLunarInfo(year, month, day, true, true, true); } QString LunarCalendarInfo::getLunarMonthDay(int year, int month, int day) { return getLunarInfo(year, month, day, false, true, true); } QString LunarCalendarInfo::getLunarDay(int year, int month, int day) { return getLunarInfo(year, month, day, false, false, true); } ukui-panel-3.0.6.4/ukui-calendar/lunarcalendarwidget/customstylePushbutton.h0000644000175000017500000000775614203402514025771 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * 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 3, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see class CustomStyle_pushbutton : public QProxyStyle { Q_OBJECT public: explicit CustomStyle_pushbutton(const QString &proxyStyleName = "windows", QObject *parent = nullptr); virtual void drawComplexControl(QStyle::ComplexControl control, const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget = nullptr) const; virtual void drawControl(QStyle::ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget = nullptr) const; virtual void drawItemPixmap(QPainter *painter, const QRect &rectangle, int alignment, const QPixmap &pixmap) const; virtual void drawItemText(QPainter *painter, const QRect &rectangle, int alignment, const QPalette &palette, bool enabled, const QString &text, QPalette::ColorRole textRole = QPalette::NoRole) const; /*! * \brief drawPrimitive * \param element 背景绘制,对应PE枚举类型 * \param option * \param painter * \param widget * \details * drawPrimitive用于绘制控件背景,比如按钮和菜单的背景, * 我们一般需要判断控件的状态来绘制不同的背景, * 比如按钮的hover和点击效果。 */ virtual void drawPrimitive(QStyle::PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget = nullptr) const; virtual QPixmap generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap, const QStyleOption *option) const; virtual QStyle::SubControl hitTestComplexControl(QStyle::ComplexControl control, const QStyleOptionComplex *option, const QPoint &position, const QWidget *widget = nullptr) const; virtual QRect itemPixmapRect(const QRect &rectangle, int alignment, const QPixmap &pixmap) const; virtual QRect itemTextRect(const QFontMetrics &metrics, const QRect &rectangle, int alignment, bool enabled, const QString &text) const; //virtual int layoutSpacing(QSizePolicy::ControlType control1, QSizePolicy::ControlType control2, Qt::Orientation orientation, const QStyleOption *option, const QWidget *widget); virtual int pixelMetric(QStyle::PixelMetric metric, const QStyleOption *option = nullptr, const QWidget *widget = nullptr) const; virtual void polish(QWidget *widget); virtual void polish(QApplication *application); virtual void polish(QPalette &palette); virtual void unpolish(QWidget *widget); virtual void unpolish(QApplication *application); virtual QSize sizeFromContents(QStyle::ContentsType type, const QStyleOption *option, const QSize &contentsSize, const QWidget *widget = nullptr) const; virtual QIcon standardIcon(QStyle::StandardPixmap standardIcon, const QStyleOption *option, const QWidget *widget) const; virtual QPalette standardPalette() const; virtual int styleHint(QStyle::StyleHint hint, const QStyleOption *option = nullptr, const QWidget *widget = nullptr, QStyleHintReturn *returnData = nullptr) const; virtual QRect subControlRect(QStyle::ComplexControl control, const QStyleOptionComplex *option, QStyle::SubControl subControl, const QWidget *widget = nullptr) const; virtual QRect subElementRect(QStyle::SubElement element, const QStyleOption *option, const QWidget *widget = nullptr) const; }; #endif // CUSTOMSTYLE_PUSHBUTTON_H ukui-panel-3.0.6.4/ukui-calendar/lunarcalendarwidget/main.cpp0000644000175000017500000000564614203402514022555 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include #include #include "xatom-helper.h" int main(int argc, char *argv[]) { QApplication a(argc, argv); a.setFont(QFont("Microsoft Yahei", 9)); #if (QT_VERSION <= QT_VERSION_CHECK(5,0,0)) #if _MSC_VER QTextCodec *codec = QTextCodec::codecForName("gbk"); #else QTextCodec *codec = QTextCodec::codecForName("utf-8"); #endif QTextCodec::setCodecForLocale(codec); QTextCodec::setCodecForCStrings(codec); QTextCodec::setCodecForTr(codec); #else QTextCodec *codec = QTextCodec::codecForName("utf-8"); QTextCodec::setCodecForLocale(codec); #endif frmLunarCalendarWidget w; w.setWindowTitle("自定义农历控件"); KWindowEffects::enableBlurBehind(w.winId(),true); // 添加窗管协议 MotifWmHints hints; hints.flags = MWM_HINTS_FUNCTIONS|MWM_HINTS_DECORATIONS; hints.functions = MWM_FUNC_ALL; hints.decorations = MWM_DECOR_BORDER; XAtomHelper::getInstance()->setWindowMotifHint(w.winId(), hints); QApplication app(argc, argv); QString locale = QLocale::system().name(); QTranslator translator; if (locale == "zh_CN"){ if (translator.load("ukui-calendar_zh_CN.qm", "/usr/share/ukui-panel/panel/resources/")) app.installTranslator(&translator); else qDebug() << "Load translations file" << locale << "failed!"; } if (locale == "tr_TR"){ if (translator.load("ukui-panel_tr.qm", "/usr/share/ukui-panel/panel/resources/")) app.installTranslator(&translator); else qDebug() << "Load translations file" << locale << "failed!"; } if (locale == "bo_CN"){ if (translator.load("ukui-panel_bo_CN.qm", "/usr/share/ukui-panel/panel/resources/")) app.installTranslator(&translator); else qDebug() << "Load translations file" << locale << "failed!"; } return a.exec(); } ukui-panel-3.0.6.4/ukui-calendar/resources/0000755000175000017500000000000014203402514017105 5ustar fengfengukui-panel-3.0.6.4/ukui-calendar/resources/ukui-calendar.desktop0000644000175000017500000000013614203402514023224 0ustar fengfeng[Desktop Entry] Name=ukui-calendar Name[zh_CN]=calendar Icon=ukui-calendar Exec=ukui-calendar ukui-panel-3.0.6.4/ukui-calendar/CMakeLists.txt0000644000175000017500000000633114203402514017636 0ustar fengfengcmake_minimum_required(VERSION 3.1.0) project(ukui-calendar) #判断编译器类型,如果是gcc编译器,则在编译选项中加入c++11支持 if(CMAKE_COMPILER_IS_GNUCXX) set(CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}") message(STATUS "optional:-std=c++11") endif(CMAKE_COMPILER_IS_GNUCXX) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) set(CMAKE_AUTOUIC ON) if(CMAKE_VERSION VERSION_LESS "3.7.0") set(CMAKE_INCLUDE_CURRENT_DIR ON) endif() find_package(Qt5DBus ${REQUIRED_QT_VERSION} REQUIRED) find_package(Qt5LinguistTools ${REQUIRED_QT_VERSION} REQUIRED) find_package(Qt5Widgets ${REQUIRED_QT_VERSION} REQUIRED) find_package(Qt5X11Extras ${REQUIRED_QT_VERSION} REQUIRED) find_package(Qt5Xml ${REQUIRED_QT_VERSION} REQUIRED) find_package(KF5WindowSystem ${KF5_MINIMUM_VERSION} REQUIRED) find_package(Qt5 ${QT_MINIMUM_VERSION} CONFIG REQUIRED Widgets DBus X11Extras LinguistTools) find_package(Qt5Xdg ${QTXDG_MINIMUM_VERSION} REQUIRED) find_package(X11 REQUIRED) find_package(Qt5LinguistTools) pkg_check_modules(GLIB2 REQUIRED glib-2.0 gio-2.0 udisks2) pkg_check_modules(QGS REQUIRED gsettings-qt) include_directories(${GLIB2_INCLUDE_DIRS}) include_directories(${QGS_INCLUDE_DIRS}) add_executable(ukui-calendar lunarcalendarwidget/customstylePushbutton.cpp lunarcalendarwidget/frmlunarcalendarwidget.cpp lunarcalendarwidget/frmlunarcalendarwidget.ui lunarcalendarwidget/lunarcalendarinfo.cpp lunarcalendarwidget/lunarcalendaritem.cpp lunarcalendarwidget/lunarcalendarmonthitem.cpp lunarcalendarwidget/lunarcalendarwidget.cpp lunarcalendarwidget/lunarcalendaryearitem.cpp lunarcalendarwidget/main.cpp lunarcalendarwidget/picturetowhite.cpp lunarcalendarwidget/customstylePushbutton.h lunarcalendarwidget/frmlunarcalendarwidget.h lunarcalendarwidget/lunarcalendarinfo.h lunarcalendarwidget/lunarcalendaritem.h lunarcalendarwidget/lunarcalendarmonthitem.h lunarcalendarwidget/lunarcalendarwidget.h lunarcalendarwidget/lunarcalendaryearitem.h lunarcalendarwidget/picturetowhite.h calendardbus.h calendardbus.cpp xatom-helper.cpp xatom-helper.h ) add_definitions(-DQT_NO_KEYWORDS) add_definitions(-DQT_MESSAGELOGCONTEXT) target_link_libraries(${PROJECT_NAME} Qt5::Widgets Qt5::DBus Qt5::X11Extras ${GLIB2_LIBRARIES} ${QGS_LIBRARIES} KF5::WindowSystem -lX11 -lukui-log4qt) install(TARGETS ukui-calendar DESTINATION bin) install(FILES resources/ukui-calendar.desktop DESTINATION "/etc/xdg/autostart/" COMPONENT Runtime ) #install(FILES # ukui-flash-disk.qrc # DESTINATION "/usr/share/ukui/ukui-panel/" # COMPONENT Runtime #) # To create a new ts file: lupdate -recursive . -target-language zh_CN -ts translation/ukui-calendar_zh_CN.ts file(GLOB TS_FILES "${CMAKE_CURRENT_SOURCE_DIR}/translation/ukui-calendar_zh_CN.ts") # cmake -DUPDATE_TRANSLATIONS=yes if (UPDATE_TRANSLATIONS) qt5_create_translation(QM_FILES ${CMAKE_SOURCE_DIR} ${TS_FILES}) else() qt5_add_translation(QM_FILES ${TS_FILES}) endif() add_custom_target(translations ALL DEPENDS ${QM_FILES}) #install(FILES ${QM_FILES} DESTINATION "/usr/share/ukui/ukui-panel/") install(FILES ${QM_FILES} DESTINATION "/usr/share/ukui-panel/panel/resources/") ukui-panel-3.0.6.4/ukui-calendar/translation/0000755000175000017500000000000014203402514017431 5ustar fengfengukui-panel-3.0.6.4/ukui-calendar/translation/ukui-calendar_zh_CN.qm0000644000175000017500000000162414203402514023600 0ustar fengfeng LunarCalendarItem 消防宣传日 Fire Publicity Day 志愿者服务日 Volunteer Service Day 全国爱眼日 National Eye Health Day 抗战纪念日 LunarCalendarWidget Year Month Today 今天 解析json文件错误! Sunday 周日 Monday 周一 Tuesday 周二 Wednesday 周三 Thursday 周四 Friday 周五 Saturday 周六 frmLunarCalendarWidget Form 整体样式 红色风格 选中样式 矩形背景 圆形背景 角标背景 图片背景 星期格式 短名称 普通名称 长名称 英文名称 显示农历 ukui-panel-3.0.6.4/ukui-calendar/calendardbus.cpp0000644000175000017500000000227614203402514020235 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include class CalendarDBus : public QObject { Q_OBJECT public: explicit CalendarDBus(QObject *parent = nullptr); public Q_SLOTS: void ShowCalendar(); Q_SIGNALS: void ShowCalendarWidget(); }; #endif // CALENDARDBUS_H ukui-panel-3.0.6.4/plugin-calendar/0000755000175000017500000000000014204636772015434 5ustar fengfengukui-panel-3.0.6.4/plugin-calendar/ukuiwebviewdialog.cpp0000644000175000017500000000507714203402514021657 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include #include #include #include #include #include #include #define CALENDAR_MAX_HEIGHT 704 #define CALENDAR_MIN_HEIGHT 600 #define CALENDAR_MAX_WIDTH 454 UkuiWebviewDialogStatus status; UkuiWebviewDialog::UkuiWebviewDialog(QWidget *parent) : QDialog(parent, Qt::FramelessWindowHint | Qt::Tool | Qt::X11BypassWindowManagerHint), ui(new Ui::UkuiWebviewDialog) { ui->setupUi(this); installEventFilter(this); } UkuiWebviewDialog::~UkuiWebviewDialog() { delete ui; } void UkuiWebviewDialog::creatwebview(int _mode, int _panelSize) { } /* * 事件过滤,检测鼠标点击外部活动区域则收回收纳栏 */ bool UkuiWebviewDialog::eventFilter(QObject *obj, QEvent *event) { if (obj == this) { if (event->type() == QEvent::MouseButtonPress) { QMouseEvent *mouseEvent = static_cast(event); if (mouseEvent->button() == Qt::LeftButton) { this->hide(); status=ST_HIDE; return true; } else if(mouseEvent->button() == Qt::RightButton) { return true; } } else if(event->type() == QEvent::ContextMenu) { return false; } else if (event->type() == QEvent::WindowDeactivate &&status==ST_SHOW) { // qDebug()<<"激活外部窗口"; this->hide(); status=ST_HIDE; return true; } else if (event->type() == QEvent::StyleChange) { } } if (!isActiveWindow()) { activateWindow(); } return false; } ukui-panel-3.0.6.4/plugin-calendar/calendar-button-bg.png0000644000175000017500000000172314203402514021575 0ustar fengfengPNG  IHDR22?tEXtSoftwareAdobe ImageReadyqe<!iTXtXML:com.adobe.xmp EHIDATx1 緅 $"""""""""""""""""""""""""""""""""""""7V#a)IENDB`ukui-panel-3.0.6.4/plugin-calendar/ukuiwebviewdialog.ui0000644000175000017500000000055214203402514021503 0ustar fengfeng UkuiWebviewDialog 0 0 400 300 Dialog ukui-panel-3.0.6.4/plugin-calendar/ukuicalendar.h0000644000175000017500000001027414204636772020260 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2012-2013 Razor team * Authors: * Kuzma Shapran * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include #include #include #include #include #include #include #include #include #include "../panel/iukuipanelplugin.h" #include "ukuiwebviewdialog.h" #include "../panel/common/ukuigridlayout.h" #include "../panel/common_fun/listengsettings.h" #include "lunarcalendarwidget/frmlunarcalendarwidget.h" class QTimer; class CalendarActiveLabel; class UkuiCalendarWebView; class IndicatorCalendar : public QWidget, public IUKUIPanelPlugin { Q_OBJECT public: IndicatorCalendar(const IUKUIPanelPluginStartupInfo &startupInfo); ~IndicatorCalendar(); virtual QWidget *widget() { return mMainWidget; } virtual QString themeId() const { return QLatin1String("Calendar"); } bool isSeparate() const { return true; } void realign()override; void initializeCalendar(); void setTimeShowStyle(); /** * @brief modifyCalendarWidget 修改日历显示位置 */ void modifyCalendarWidget(); Q_SIGNALS: void deactivated(); private Q_SLOTS: void checkUpdateTime(); void updateTimeText(); void hidewebview(); void CalendarWidgetShow(); void ListenForManualSettingTime(); private: QWidget *mMainWidget; frmLunarCalendarWidget *w; UkuiWebviewDialog *mWebViewDiag; bool mbActived; bool mbHasCreatedWebView; int font_size; CalendarActiveLabel *mContent; UKUi::GridLayout *mLayout; QString timeState; QTimer *mTimer; QTimer *mCheckTimer; int mUpdateInterval; int16_t mViewWidht; int16_t mViewHeight; QString mActiveTimeZone; QGSettings *gsettings; QGSettings *fgsettings; QString hourSystemMode; QString hourSystem_24_horzontal; QString hourSystem_24_vartical; QString hourSystem_12_horzontal; QString hourSystem_12_vartical; QString current_date; IUKUIPanelPlugin * mPlugin; QProcess *mProcess; QTranslator *m_translator; private: void translator(); }; #define SERVICE "org.ukui.panel.calendar" #define PATH "/calendarWidget" #define INTERFACE "org.ukui.panel.calendar" class CalendarActiveLabel : public QLabel { Q_OBJECT public: explicit CalendarActiveLabel(IUKUIPanelPlugin *plugin,QWidget * = NULL); IUKUIPanelPlugin * mPlugin; int16_t mViewWidht = 440; int16_t mViewHeight = 600 ; int changeHight = 0; void changeWidowpos(); protected: /** * @brief contextMenuEvent 右键菜单设置项 * @param event */ virtual void contextMenuEvent(QContextMenuEvent *event); void mousePressEvent(QMouseEvent *event); private: frmLunarCalendarWidget *w; QDBusInterface *mInterface; Q_SIGNALS: void pressTimeText(); private Q_SLOTS: /** * @brief setControlTime 右键菜单选项,在控制面板设置时间 */ void setControlTime(); }; class UKUICalendarPluginLibrary: public QObject, public IUKUIPanelPluginLibrary { Q_OBJECT Q_PLUGIN_METADATA(IID "ukui.org/Panel/PluginInterface/3.0") Q_INTERFACES(IUKUIPanelPluginLibrary) public: IUKUIPanelPlugin *instance(const IUKUIPanelPluginStartupInfo &startupInfo) const { return new IndicatorCalendar(startupInfo); } }; ukui-panel-3.0.6.4/plugin-calendar/style/0000755000175000017500000000000014204636772016574 5ustar fengfengukui-panel-3.0.6.4/plugin-calendar/style/indicators.css0000644000175000017500000000245414204636772021452 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include "../panel/iukuipanelplugin.h" namespace Ui { class UkuiWebviewDialog; } enum UkuiWebviewDialogStatus{ST_HIDE,ST_SHOW}; enum CalendarShowMode { lunarSunday = 0,//show lunar and first day a week is sunday lunarMonday = 1,//show lunar and first day a week is monday solarSunday = 2,//show solar and first day a week is sunday solarMonday = 3,//show solar and first day a week is monday Unknown = 0xff }; class UkuiWebviewDialog : public QDialog { Q_OBJECT public: explicit UkuiWebviewDialog(QWidget *parent = nullptr); ~UkuiWebviewDialog(); void creatwebview(int _mode, int _panelSize); void showinfo(QString string); Q_SIGNALS: void deactivated(); private: Ui::UkuiWebviewDialog *ui; QSize mQsize; protected: // virtual bool event(QEvent *event); // bool nativeEvent(const QByteArray &eventType, void *message, long *result); bool eventFilter(QObject *, QEvent *); }; #endif // UKUIWEBVIEWDIALOG_H ukui-panel-3.0.6.4/plugin-calendar/lunarcalendarwidget/0000755000175000017500000000000014204636772021453 5ustar fengfengukui-panel-3.0.6.4/plugin-calendar/lunarcalendarwidget/frmlunarcalendarwidget.h0000644000175000017500000000334614203402514026336 0ustar fengfeng /* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include namespace Ui { class frmLunarCalendarWidget; } class frmLunarCalendarWidget : public QWidget { Q_OBJECT public: explicit frmLunarCalendarWidget(QWidget *parent = 0); ~frmLunarCalendarWidget(); bool status; protected: void paintEvent(QPaintEvent *); private: Ui::frmLunarCalendarWidget *ui; QGSettings *transparency_gsettings; QGSettings *calendar_gsettings; bool eventFilter(QObject *, QEvent *); private Q_SLOTS: void initForm(); void cboxCalendarStyle_currentIndexChanged(int index); void cboxSelectType_currentIndexChanged(int index); void cboxWeekNameFormat_currentIndexChanged(bool FirstDayisSun); void ckShowLunar_stateChanged(bool arg1); void changeUpSize(); void changeDownSize(); Q_SIGNALS: void yijiChangeUp(); void yijiChangeDown(); }; #endif // FRMLUNARCALENDARWIDGET_H ukui-panel-3.0.6.4/plugin-calendar/lunarcalendarwidget/picturetowhite.cpp0000644000175000017500000000633014203402514025220 0ustar fengfeng/* * Copyright (C) 2020 Tianjin KYLIN Information Technology Co., Ltd. * * 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 3, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see get(STYLE_NAME).toString()) && m_pgsettings->get(STYLE_NAME).toString() == STYLE_NAME_KEY_LIGHT){ tray_icon_color = TRAY_ICON_COLOR_LOGHT; }else{ tray_icon_color = TRAY_ICON_COLOR_DRAK; } } connect(m_pgsettings, &QGSettings::changed, this, [=] (const QString &key) { if (key==STYLE_NAME) { if (stylelist.contains(m_pgsettings->get(STYLE_NAME).toString()) && m_pgsettings->get(STYLE_NAME).toString() == STYLE_NAME_KEY_LIGHT){ tray_icon_color = TRAY_ICON_COLOR_LOGHT; }else{ tray_icon_color = TRAY_ICON_COLOR_DRAK; } } }); } QPixmap PictureToWhite::drawSymbolicColoredPixmap(const QPixmap &source) { QColor gray(128,128,128); QColor standard (31,32,34); QImage img = source.toImage(); for (int x = 0; x < img.width(); x++) { for (int y = 0; y < img.height(); y++) { auto color = img.pixelColor(x, y); if (color.alpha() > 0) { if (qAbs(color.red()-gray.red()) < 20 && qAbs(color.green()-gray.green()) < 20 && qAbs(color.blue()-gray.blue()) < 20) { color.setRed(tray_icon_color); color.setGreen(tray_icon_color); color.setBlue(tray_icon_color); img.setPixelColor(x, y, color); } else if (qAbs(color.red()-standard.red()) < 20 && qAbs(color.green()-standard.green()) < 20 && qAbs(color.blue()-standard.blue()) < 20) { // qDebug()<<"反色"< frmLunarCalendarWidget 0 0 600 500 Form 0 0 0 0 0 0 整体样式 90 0 红色风格 选中样式 90 0 矩形背景 圆形背景 角标背景 图片背景 星期格式 90 0 短名称 普通名称 长名称 英文名称 显示农历 true Qt::Horizontal 40 20 LunarCalendarWidget QWidget
lunarcalendarwidget.h
1
ukui-panel-3.0.6.4/plugin-calendar/lunarcalendarwidget/customstylePushbutton.cpp0000644000175000017500000002136614203402514026636 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * 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 3, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include CustomStyle_pushbutton::CustomStyle_pushbutton(const QString &proxyStyleName, QObject *parent) : QProxyStyle (proxyStyleName) { Q_UNUSED(parent); } void CustomStyle_pushbutton::drawComplexControl(QStyle::ComplexControl control, const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget) const { return QProxyStyle::drawComplexControl(control, option, painter, widget); } void CustomStyle_pushbutton::drawControl(QStyle::ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const { switch (element) { case QStyle::CE_PushButton: { QStyleOptionButton button = *qstyleoption_cast(option); button.palette.setColor(QPalette::HighlightedText, button.palette.buttonText().color()); return QProxyStyle::drawControl(element, &button, painter, widget); break; } default: break; } return QProxyStyle::drawControl(element, option, painter, widget); } void CustomStyle_pushbutton::drawItemPixmap(QPainter *painter, const QRect &rectangle, int alignment, const QPixmap &pixmap) const { return QProxyStyle::drawItemPixmap(painter, rectangle, alignment, pixmap); } void CustomStyle_pushbutton::drawItemText(QPainter *painter, const QRect &rectangle, int alignment, const QPalette &palette, bool enabled, const QString &text, QPalette::ColorRole textRole) const { return QProxyStyle::drawItemText(painter, rectangle, alignment, palette, enabled, text, textRole); } /// 我们重写button的绘制方法,通过state和当前动画的状态以及value值改变相关的绘制条件 /// 这里通过判断hover与否,动态的调整painter的透明度然后绘制背景 /// 需要注意的是,默认控件的绘制流程只会触发一次,而动画需要我们在一段时间内不停绘制才行, /// 要使得动画能够持续,我们需要使用QWidget::update()在动画未完成时, /// 手动更新一次,这样button将在一段时间后再次调用draw方法,从而达到更新动画的效果 /// /// 需要注意绘制背景的流程会因主题不同而产生差异,所以这一部分代码在一些主题中未必正常, /// 如果你需要自己实现一个主题,这同样是你需要注意和考虑的点 void CustomStyle_pushbutton::drawPrimitive(QStyle::PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const { // if (element == PE_PanelButtonCommand) { // qDebug()<<"draw pe button"; // if (widget) { // bool isPressed = false; // bool isHover = false; // if (!option->state.testFlag(State_Sunken)) { // if (option->state.testFlag(State_MouseOver)) { // isHover = true; // } // } else { // isPressed = true; // } // QStyleOption opt = *option; // if (isHover) { // QColor color(255,255,255,51); // opt.palette.setColor(QPalette::Highlight, color); // } // if (isPressed) { // QColor color(255,255,255,21); // opt.palette.setColor(QPalette::Highlight, color); // } // if (!isHover && !isPressed) { // QColor color(255,255,255,31); // opt.palette.setColor(QPalette::Button,color); // } // return QProxyStyle::drawPrimitive(element, &opt, painter, widget); // } // } // return QProxyStyle::drawPrimitive(element, option, painter, widget); if (element == PE_PanelButtonCommand) { if (widget) { if (option->state & State_MouseOver) { if (option->state & State_Sunken) { painter->save(); painter->setRenderHint(QPainter::Antialiasing,true); painter->setPen(Qt::NoPen); QColor color(255,255,255,21); painter->setBrush(color); painter->drawRoundedRect(option->rect, 4, 4); painter->restore(); } else { painter->save(); painter->setRenderHint(QPainter::Antialiasing,true); painter->setPen(Qt::NoPen); QColor color(255,255,255,51); painter->setBrush(color); painter->drawRoundedRect(option->rect, 4, 4); painter->restore(); } } else { painter->save(); painter->setRenderHint(QPainter::Antialiasing,true); painter->setPen(Qt::NoPen); QColor color(255,255,255,0); painter->setBrush(color); painter->drawRoundedRect(option->rect, 4, 4); painter->restore(); } return; } } return QProxyStyle::drawPrimitive(element, option, painter, widget); } QPixmap CustomStyle_pushbutton::generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap, const QStyleOption *option) const { return QProxyStyle::generatedIconPixmap(iconMode, pixmap, option); } QStyle::SubControl CustomStyle_pushbutton::hitTestComplexControl(QStyle::ComplexControl control, const QStyleOptionComplex *option, const QPoint &position, const QWidget *widget) const { return QProxyStyle::hitTestComplexControl(control, option, position, widget); } QRect CustomStyle_pushbutton::itemPixmapRect(const QRect &rectangle, int alignment, const QPixmap &pixmap) const { return QProxyStyle::itemPixmapRect(rectangle, alignment, pixmap); } QRect CustomStyle_pushbutton::itemTextRect(const QFontMetrics &metrics, const QRect &rectangle, int alignment, bool enabled, const QString &text) const { return QProxyStyle::itemTextRect(metrics, rectangle, alignment, enabled, text); } int CustomStyle_pushbutton::pixelMetric(QStyle::PixelMetric metric, const QStyleOption *option, const QWidget *widget) const { return QProxyStyle::pixelMetric(metric, option, widget); } /// 我们需要将动画与widget一一对应起来, /// 在一个style的生命周期里,widget只会进行polish和unpolish各一次, /// 所以我们可以在polish时将widget与一个新的动画绑定,并且对应的在unpolish中解绑定 void CustomStyle_pushbutton::polish(QWidget *widget) { return QProxyStyle::polish(widget); } void CustomStyle_pushbutton::polish(QApplication *application) { return QProxyStyle::polish(application); } void CustomStyle_pushbutton::polish(QPalette &palette) { return QProxyStyle::polish(palette); } void CustomStyle_pushbutton::unpolish(QWidget *widget) { return QProxyStyle::unpolish(widget); } void CustomStyle_pushbutton::unpolish(QApplication *application) { return QProxyStyle::unpolish(application); } QSize CustomStyle_pushbutton::sizeFromContents(QStyle::ContentsType type, const QStyleOption *option, const QSize &contentsSize, const QWidget *widget) const { return QProxyStyle::sizeFromContents(type, option, contentsSize, widget); } QIcon CustomStyle_pushbutton::standardIcon(QStyle::StandardPixmap standardIcon, const QStyleOption *option, const QWidget *widget) const { return QProxyStyle::standardIcon(standardIcon, option, widget); } QPalette CustomStyle_pushbutton::standardPalette() const { return QProxyStyle::standardPalette(); } int CustomStyle_pushbutton::styleHint(QStyle::StyleHint hint, const QStyleOption *option, const QWidget *widget, QStyleHintReturn *returnData) const { return QProxyStyle::styleHint(hint, option, widget, returnData); } QRect CustomStyle_pushbutton::subControlRect(QStyle::ComplexControl control, const QStyleOptionComplex *option, QStyle::SubControl subControl, const QWidget *widget) const { return QProxyStyle::subControlRect(control, option, subControl, widget); } QRect CustomStyle_pushbutton::subElementRect(QStyle::SubElement element, const QStyleOption *option, const QWidget *widget) const { return QProxyStyle::subElementRect(element, option, widget); } ukui-panel-3.0.6.4/plugin-calendar/lunarcalendarwidget/statelabel.h0000644000175000017500000000204614203402514023726 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include class statelabel : public QLabel { Q_OBJECT public: statelabel(); protected: void mousePressEvent(QMouseEvent *event); Q_SIGNALS : void labelclick(); }; #endif // STATELABEL_H ukui-panel-3.0.6.4/plugin-calendar/lunarcalendarwidget/picturetowhite.h0000644000175000017500000000307214203402514024665 0ustar fengfeng/* * Copyright (C) 2020 Tianjin KYLIN Information Technology Co., Ltd. * * 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 3, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include #include #define ORG_UKUI_STYLE "org.ukui.style" #define STYLE_NAME "styleName" #define STYLE_NAME_KEY_DARK "ukui-dark" #define STYLE_NAME_KEY_DEFAULT "ukui-default" #define STYLE_NAME_KEY_BLACK "ukui-black" #define STYLE_NAME_KEY_LIGHT "ukui-light" #define STYLE_NAME_KEY_WHITE "ukui-white" #define TRAY_ICON_COLOR_LOGHT 0 #define TRAY_ICON_COLOR_DRAK 255 class PictureToWhite : public QObject { Q_OBJECT public: explicit PictureToWhite(QObject *parent = nullptr); void initGsettingValue(); QPixmap drawSymbolicColoredPixmap(const QPixmap &source); public: QGSettings *m_pgsettings; int tray_icon_color; }; #endif // PICTURETOWHITE_H ukui-panel-3.0.6.4/plugin-calendar/lunarcalendarwidget/lunarcalendarwidget.cpp0000644000175000017500000014433014203402514026163 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #define PANEL_CONTROL_IN_CALENDAR "org.ukui.control-center.panel.plugins" #define LUNAR_KEY "calendar" #define FIRST_DAY_KEY "firstday" #define ORG_UKUI_STYLE "org.ukui.style" #define STYLE_NAME "styleName" #define STYLE_NAME_KEY_DARK "ukui-dark" #define STYLE_NAME_KEY_DEFAULT "ukui-default" #define STYLE_NAME_KEY_BLACK "ukui-black" #define STYLE_NAME_KEY_LIGHT "ukui-light" #define STYLE_NAME_KEY_WHITE "ukui-white" #define ICON_COLOR_LOGHT 255 #define ICON_COLOR_DRAK 0 LunarCalendarWidget::LunarCalendarWidget(QWidget *parent) : QWidget(parent) { analysisWorktimeJs(); const QByteArray calendar_id(PANEL_CONTROL_IN_CALENDAR); if(QGSettings::isSchemaInstalled(calendar_id)){ calendar_gsettings = new QGSettings(calendar_id); //农历切换监听与日期显示格式 connect(calendar_gsettings, &QGSettings::changed, this, [=] (const QString &key){ if(key == LUNAR_KEY){ if(calendar_gsettings->get("calendar").toString() == "lunar") { QLocale locale = (QLocale::system().name() == "zh_CN" ? (QLocale::Chinese) : (QLocale::English)); if(locale == QLocale::Chinese){ //农历模式且是中文模式 qDebug()<<"语言模式1:"<setVisible(true); yijiWidget->setVisible(true); }else{ qDebug()<<"农历模式但非中文模式则不能显示农历相关"; lunarstate = false; labWidget->setVisible(false); yijiWidget->setVisible(false); } } else { //公历 lunarstate = false; labWidget->setVisible(false); yijiWidget->setVisible(false); } _timeUpdate(); } if(key == "date") { if(calendar_gsettings->get("date").toString() == "cn"){ dateShowMode = "yyyy/MM/dd dddd"; } else { dateShowMode = "yyyy-MM-dd dddd"; } } }); if(calendar_gsettings->get("date").toString() == "cn"){ dateShowMode = "yyyy/MM/dd dddd"; } else { dateShowMode = "yyyy-MM-dd dddd"; } //监听12/24小时制 connect(calendar_gsettings, &QGSettings::changed, this, [=] (const QString &keys){ timemodel = calendar_gsettings->get("hoursystem").toString(); _timeUpdate(); }); timemodel = calendar_gsettings->get("hoursystem").toString(); } else { dateShowMode = "yyyy/MM/dd dddd"; //无设置默认公历 lunarstate = true; } setWindowOpacity(0.7); setAttribute(Qt::WA_TranslucentBackground);//设置窗口背景透明 setProperty("useSystemStyleBlur", true); //设置毛玻璃效果 //判断图形字体是否存在,不存在则加入 QFontDatabase fontDb; if (!fontDb.families().contains("FontAwesome")) { int fontId = fontDb.addApplicationFont(":/image/fontawesome-webfont.ttf"); QStringList fontName = fontDb.applicationFontFamilies(fontId); if (fontName.count() == 0) { qDebug() << "load fontawesome-webfont.ttf error"; } } if (fontDb.families().contains("FontAwesome")) { iconFont = QFont("FontAwesome"); #if (QT_VERSION >= QT_VERSION_CHECK(4,8,0)) iconFont.setHintingPreference(QFont::PreferNoHinting); #endif } btnYear = new QPushButton; btnMonth = new QPushButton; btnToday = new QPushButton; btnClick = false; calendarStyle = CalendarStyle_Red; date = QDate::currentDate(); widgetTime = new QWidget; timeShow = new QVBoxLayout(widgetTime); datelabel =new QLabel(this); timelabel = new QLabel(this); lunarlabel = new QLabel(this); widgetTime->setObjectName("widgetTime"); timeShow->setContentsMargins(0, 0, 0, 0); initWidget(); if(QGSettings::isSchemaInstalled(calendar_id)){ //初始化农历/公历显示方式 if(calendar_gsettings->get("calendar").toString() == "lunar") { QLocale locale = (QLocale::system().name() == "zh_CN" ? (QLocale::Chinese) : (QLocale::English)); qDebug()<<"语言模式2:"<setVisible(true); yijiWidget->setVisible(true); }else{ qDebug()<<"农历模式但非中文模式则不能显示农历相关"; lunarstate = false; labWidget->setVisible(false); yijiWidget->setVisible(false); } } else { //公历 lunarstate = false; labWidget->setVisible(false); yijiWidget->setVisible(false); } } //切换主题 const QByteArray style_id(ORG_UKUI_STYLE); QStringList stylelist; stylelist<get(STYLE_NAME).toString()); setColor(dark_style); } connect(style_settings, &QGSettings::changed, this, [=] (const QString &key){ if(key==STYLE_NAME){ dark_style=stylelist.contains(style_settings->get(STYLE_NAME).toString()); _timeUpdate(); setColor(dark_style); }else{ qDebug()<<"key!=STYLE_NAME"; } }); // //实时监听系统字体的改变 // const QByteArray id("org.ukui.style"); // QGSettings * fontSetting = new QGSettings(id, QByteArray(), this); // connect(fontSetting, &QGSettings::changed,[=](QString key) { // if ("systemFont" == key || "systemFontSize" ==key) { // QFont font = this->font(); // btnToday->setFont(font); // cboxYearandMonth->setFont(font); // for (int i = 0; i < 42; i++) { // dayItems.value(i)->setFont(font); // dayItems.value(i)->repaint(); // } // for (int i = 0; i < 7; i++) { // labWeeks.value(i)->setFont(font); // labWeeks.value(i)->repaint(); // } // } // }); timer = new QTimer(); connect(timer,SIGNAL(timeout()),this,SLOT(timerUpdate())); timer->start(1000); locale = QLocale::system().name(); if(QGSettings::isSchemaInstalled(calendar_id)){ setWeekNameFormat(calendar_gsettings->get(FIRST_DAY_KEY).toString() == "sunday"); setShowLunar(calendar_gsettings->get(LUNAR_KEY).toString() == "lunar"); } setLocaleCalendar();//设置某区域下日历的显示 //监听手动更改时间,后期找到接口进行替换 // QTimer::singleShot(1000,this,[=](){ListenForManualSetTime();}); } LunarCalendarWidget::~LunarCalendarWidget() { } /* * @brief 设置日历的背景及文字颜色 * 参数: * weekColor 周六及周日文字颜色 */ void LunarCalendarWidget::setColor(bool mdark_style) { const QByteArray calendar_id(PANEL_CONTROL_IN_CALENDAR); if(mdark_style){ weekTextColor = QColor(0, 0, 0); weekBgColor = QColor(180, 180, 180); if(QGSettings::isSchemaInstalled(calendar_id)){ showLunar = calendar_gsettings->get(LUNAR_KEY).toString() == "lunar"; } bgImage = ":/image/bg_calendar.png"; selectType = SelectType_Rect; borderColor = QColor(180, 180, 180); weekColor = QColor(255, 255, 255); superColor = QColor(255, 129, 6); lunarColor = QColor(233, 90, 84); currentTextColor = QColor(255, 255, 255); otherTextColor = QColor(125, 125, 125); selectTextColor = QColor(255, 255, 255); hoverTextColor = QColor(0, 0, 0); currentLunarColor = QColor(150, 150, 150); otherLunarColor = QColor(200, 200, 200); selectLunarColor = QColor(255, 255, 255); hoverLunarColor = QColor(250, 250, 250); currentBgColor = QColor(0, 0, 0); otherBgColor = QColor(240, 240, 240); selectBgColor = QColor(80, 100, 220); hoverBgColor = QColor(80, 190, 220); }else{ weekTextColor = QColor(255, 255, 255); weekBgColor = QColor(0, 0, 0); if(QGSettings::isSchemaInstalled(calendar_id)){ showLunar = calendar_gsettings->get(LUNAR_KEY).toString() == "lunar"; } bgImage = ":/image/bg_calendar.png"; selectType = SelectType_Rect; borderColor = QColor(180, 180, 180); weekColor = QColor(0, 0, 0); superColor = QColor(255, 129, 6); lunarColor = QColor(233, 90, 84); currentTextColor = QColor(0, 0, 0); otherTextColor = QColor(125, 125, 125); selectTextColor = QColor(255, 255, 255); hoverTextColor = QColor(0, 0, 0); currentLunarColor = QColor(150, 150, 150); otherLunarColor = QColor(200, 200, 200); selectLunarColor = QColor(255, 255, 255); hoverLunarColor = QColor(250, 250, 250); currentBgColor = QColor(250, 250, 250); otherBgColor = QColor(240, 240, 240); selectBgColor = QColor(80, 100, 220); hoverBgColor = QColor(80, 190, 220); } initStyle(); } void LunarCalendarWidget::_timeUpdate() { QDateTime time = QDateTime::currentDateTime(); QLocale locale /*= (QLocale::system().name() == "zh_CN" ? (QLocale::Chinese) : (QLocale::English))*/; QString _time; if(timemodel == "12") { _time = locale.toString(time,"Ahh:mm:ss"); } else { _time = locale.toString(time,"hh:mm:ss"); } QFont font; datelabel->setText(_time); font.setPointSize(22); datelabel->setFont(font); datelabel->setAlignment(Qt::AlignHCenter); QString strHoliday; QString strSolarTerms; QString strLunarFestival; QString strLunarYear; QString strLunarMonth; QString strLunarDay; LunarCalendarInfo::Instance()->getLunarCalendarInfo(locale.toString(time,"yyyy").toInt(), locale.toString(time,"MM").toInt(), locale.toString(time,"dd").toInt(), strHoliday, strSolarTerms, strLunarFestival, strLunarYear, strLunarMonth, strLunarDay); QString _date = locale.toString(time,dateShowMode); if (lunarstate) { _date = _date + " "+strLunarMonth + strLunarDay; } timelabel->setText(_date); font.setPointSize(12); timelabel->setFont(font); timelabel->setAlignment(Qt::AlignHCenter); } void LunarCalendarWidget::timerUpdate() { _timeUpdate(); } void LunarCalendarWidget::initWidget() { setObjectName("lunarCalendarWidget"); //顶部widget QWidget *widgetTop = new QWidget; widgetTop->setObjectName("widgetTop"); widgetTop->setMinimumHeight(35); //上个月的按钮 btnPrevYear = new statelabel; btnPrevYear->setObjectName("btnPrevYear"); btnPrevYear->setFixedWidth(35); btnPrevYear->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding); QPixmap pixmap1 = QIcon::fromTheme("strIconPath", QIcon::fromTheme("pan-up-symbolic")).pixmap(QSize(24, 24)); PictureToWhite pictToWhite1; btnPrevYear->setPixmap(pictToWhite1.drawSymbolicColoredPixmap(pixmap1)); btnPrevYear->setProperty("useIconHighlightEffect", 0x2); //下个月按钮 btnNextYear = new statelabel; btnNextYear->setObjectName("btnNextYear"); btnNextYear->setFixedWidth(35); btnNextYear->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding); QPixmap pixmap2 = QIcon::fromTheme("strIconPath", QIcon::fromTheme("pan-down-symbolic")).pixmap(QSize(24, 24)); PictureToWhite pictToWhite2; btnNextYear->setPixmap(pictToWhite2.drawSymbolicColoredPixmap(pixmap2)); btnNextYear->setProperty("useIconHighlightEffect", 0x2); m_font.setPointSize(12); //转到年显示 btnYear->setObjectName("btnYear"); btnYear->setFocusPolicy(Qt::NoFocus); btnYear->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding); btnYear->setFont(m_font); btnYear->setText(tr("Year")); btnYear->setToolTip(tr("Year")); btnYear->setStyle(new CustomStyle_pushbutton("ukui-default")); connect(btnYear,&QPushButton::clicked,this,&LunarCalendarWidget::yearWidgetChange); //转到月显示 btnMonth->setObjectName("btnMonth"); btnMonth->setFocusPolicy(Qt::NoFocus); btnMonth->setFont(m_font); btnMonth->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding); btnMonth->setText(tr("Month")); btnMonth->setToolTip(tr("Month")); btnMonth->setStyle(new CustomStyle_pushbutton("ukui-default")); connect(btnMonth,&QPushButton::clicked,this,&LunarCalendarWidget::monthWidgetChange); //转到今天 btnToday->setObjectName("btnToday"); btnToday->setFocusPolicy(Qt::NoFocus); btnToday->setFont(m_font); //btnToday->setFixedWidth(40); btnToday->setStyle(new CustomStyle_pushbutton("ukui-default")); btnToday->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding); btnToday->setText(tr("Today")); btnToday->setToolTip(tr("Today")); //年份与月份下拉框 暂不用此 cboxYearandMonth = new QComboBox; cboxYearandMonth->setStyleSheet("QComboBox{background: transparent;font-size: 20px;}" "QComboBox::down-down{width: 1px;}"); cboxYearandMonth->setFixedWidth(100); cboxYearandMonth->setObjectName("cboxYearandMonth"); for (int i = 1901; i <= 2099; i++) { for (int j = 1; j <= 12; j++) { cboxYearandMonth->addItem(QString("%1.%2").arg(i).arg(j)); } } cboxYearandMonthLabel = new QLabel(); cboxYearandMonthLabel->setFixedWidth(100); cboxYearandMonthLabel->setFont(m_font); //中间用个空widget隔开 // QWidget *widgetBlank1 = new QWidget; // widgetBlank1->setFixedWidth(180); // QWidget *widgetBlank2 = new QWidget; // widgetBlank2->setFixedWidth(5); // QWidget *widgetBlank3 = new QWidget; // widgetBlank3->setFixedWidth(40); //顶部横向布局 QHBoxLayout *layoutTop = new QHBoxLayout(widgetTop); layoutTop->setContentsMargins(0, 0, 0, 9); // layoutTop->addItem(new QSpacerItem(5,1));//去掉按钮间的间隔限制 layoutTop->addWidget(cboxYearandMonthLabel); layoutTop->addStretch(); layoutTop->addWidget(btnNextYear); layoutTop->addWidget(btnPrevYear); layoutTop->addStretch(); layoutTop->addWidget(btnYear); layoutTop->addWidget(btnMonth); layoutTop->addWidget(btnToday); layoutTop->addStretch(); // layoutTop->addItem(new QSpacerItem(10,1));//去掉按钮间的间隔限制 //时间 widgetTime->setMinimumHeight(50); timeShow->addWidget(datelabel);//, Qt::AlignHCenter); timeShow->addWidget(timelabel);//,Qt::AlignHCenter); //星期widget widgetWeek = new QWidget; widgetWeek->setObjectName("widgetWeek"); widgetWeek->setMinimumHeight(30); //星期布局 QHBoxLayout *layoutWeek = new QHBoxLayout(widgetWeek); layoutWeek->setMargin(0); layoutWeek->setSpacing(0); for (int i = 0; i < 7; i++) { QLabel *lab = new QLabel; lab->setFont(m_font); lab->setAlignment(Qt::AlignCenter); layoutWeek->addWidget(lab); labWeeks.append(lab); } //日期标签widget widgetDayBody = new QWidget; widgetDayBody->setObjectName("widgetDayBody"); //日期标签布局 QGridLayout *layoutBodyDay = new QGridLayout(widgetDayBody); layoutBodyDay->setMargin(1); layoutBodyDay->setHorizontalSpacing(0); layoutBodyDay->setVerticalSpacing(0); //逐个添加日标签 for (int i = 0; i < 42; i++) { LunarCalendarItem *lab = new LunarCalendarItem; lab->worktime = worktime; connect(lab, SIGNAL(clicked(QDate, LunarCalendarItem::DayType)), this, SLOT(clicked(QDate, LunarCalendarItem::DayType))); layoutBodyDay->addWidget(lab, i / 7, i % 7); dayItems.append(lab); } //年份标签widget widgetYearBody = new QWidget; widgetYearBody->setObjectName("widgetYearBody"); //年份标签布局 QGridLayout *layoutBodyYear = new QGridLayout(widgetYearBody); layoutBodyYear->setMargin(1); layoutBodyYear->setHorizontalSpacing(0); layoutBodyYear->setVerticalSpacing(0); //逐个添加年标签 for (int i = 0; i < 12; i++) { LunarCalendarYearItem *labYear = new LunarCalendarYearItem; connect(labYear, SIGNAL(yearMessage(QDate, LunarCalendarYearItem::DayType)), this, SLOT(updateYearClicked(QDate, LunarCalendarYearItem::DayType))); layoutBodyYear->addWidget(labYear, i / 3, i % 3); yearItems.append(labYear); } widgetYearBody->hide(); //月份标签widget widgetmonthBody = new QWidget; widgetmonthBody->setObjectName("widgetmonthBody"); //月份标签布局 QGridLayout *layoutBodyMonth = new QGridLayout(widgetmonthBody); layoutBodyMonth->setMargin(1); layoutBodyMonth->setHorizontalSpacing(0); layoutBodyMonth->setVerticalSpacing(0); //逐个添加月标签 for (int i = 0; i < 12; i++) { LunarCalendarMonthItem *labMonth = new LunarCalendarMonthItem; connect(labMonth, SIGNAL(monthMessage(QDate, LunarCalendarMonthItem::DayType)), this, SLOT(updateMonthClicked(QDate, LunarCalendarMonthItem::DayType))); layoutBodyMonth->addWidget(labMonth, i / 3, i % 3); monthItems.append(labMonth); } widgetmonthBody->hide(); QFont font; font.setPointSize(12); labWidget = new QWidget(); labBottom = new QLabel(); yijichooseLabel = new QLabel(); yijichooseLabel->setText("宜忌"); yijichooseLabel->setFont(font); labBottom->setFont(font); yijichoose = new QCheckBox(); labLayout = new QHBoxLayout(); labLayout->addWidget(labBottom); labLayout->addItem(new QSpacerItem(100,5,QSizePolicy::Expanding,QSizePolicy::Minimum)); labLayout->addWidget(yijichooseLabel); labLayout->addWidget(yijichoose); labWidget->setLayout(labLayout); yijiLayout = new QVBoxLayout; yijiWidget = new QWidget; // yijiWidget->setFixedHeight(60); yiLabel = new QLabel(); jiLabel = new QLabel(); yiLabel->setFont(font); jiLabel->setFont(font); yijiLayout->addWidget(yiLabel); yijiLayout->addWidget(jiLabel); yijiWidget->setLayout(yijiLayout); yiLabel->setVisible(false); jiLabel->setVisible(false); connect(yijichoose,&QRadioButton::clicked,this,&LunarCalendarWidget::customButtonsClicked); //主布局 lineUp = new m_PartLineWidget(); lineDown = new m_PartLineWidget(); lineUp->setFixedSize(440, 1); lineDown->setFixedSize(440, 1); QVBoxLayout *verLayoutCalendar = new QVBoxLayout(this); verLayoutCalendar->setMargin(0); verLayoutCalendar->setSpacing(0); verLayoutCalendar->addWidget(widgetTime); verLayoutCalendar->addItem(new QSpacerItem(10,10)); verLayoutCalendar->addWidget(lineUp); verLayoutCalendar->addItem(new QSpacerItem(10,10)); verLayoutCalendar->addWidget(widgetTop); verLayoutCalendar->addWidget(widgetWeek); verLayoutCalendar->addWidget(widgetDayBody, 1); verLayoutCalendar->addWidget(widgetYearBody, 1); verLayoutCalendar->addWidget(widgetmonthBody, 1); verLayoutCalendar->addWidget(lineDown); verLayoutCalendar->addWidget(labWidget); verLayoutCalendar->addWidget(yijiWidget); //绑定按钮和下拉框信号 // connect(btnPrevYear, SIGNAL(clicked(bool)), this, SLOT(showPreviousYear())); // connect(btnNextYear, SIGNAL(clicked(bool)), this, SLOT(showNextYear())); connect(btnPrevYear, SIGNAL(labelclick()), this, SLOT(showPreviousMonth())); connect(btnNextYear, SIGNAL(labelclick()), this, SLOT(showNextMonth())); connect(btnToday, SIGNAL(clicked(bool)), this, SLOT(showToday())); connect(cboxYearandMonth, SIGNAL(currentIndexChanged(QString)), this, SLOT(yearChanged(QString))); // connect(cboxMonth, SIGNAL(currentIndexChanged(QString)), this, SLOT(monthChanged(QString))); } //设置日历的地区 void LunarCalendarWidget::setLocaleCalendar() { QStringList res = getLocale(); qDebug()<<"设置区域:"<setText("周日"); labWeeks.at(1)->setText("周一"); labWeeks.at(2)->setText("周二"); labWeeks.at(3)->setText("周三"); labWeeks.at(4)->setText("周四"); labWeeks.at(5)->setText("周五"); labWeeks.at(6)->setText("周六"); } else { labWeeks.at(0)->setText("周一"); labWeeks.at(1)->setText("周二"); labWeeks.at(2)->setText("周三"); labWeeks.at(3)->setText("周四"); labWeeks.at(4)->setText("周五"); labWeeks.at(5)->setText("周六"); labWeeks.at(6)->setText("周日"); } }else{ if (FirstdayisSun){ labWeeks.at(0)->setText("Sun"); labWeeks.at(1)->setText("Mon"); labWeeks.at(2)->setText("Tue"); labWeeks.at(3)->setText("Wed"); labWeeks.at(4)->setText("Thur"); labWeeks.at(5)->setText("Fri"); labWeeks.at(6)->setText("Sat"); }else { labWeeks.at(0)->setText("Mon"); labWeeks.at(1)->setText("Tue"); labWeeks.at(2)->setText("Wed"); labWeeks.at(3)->setText("Thur"); labWeeks.at(4)->setText("Fri"); labWeeks.at(5)->setText("Sat"); labWeeks.at(6)->setText("Sun"); } } } //获取指定地区的编号代码 QStringList LunarCalendarWidget::getLocale() { //判断区域(美国/中国) QString objpath; unsigned int uid = getuid(); objpath = objpath +"/org/freedesktop/Accounts/User"+QString::number(uid); QString formats; QString language; QStringList result; QDBusInterface localeInterface("org.freedesktop.Accounts", objpath, "org.freedesktop.DBus.Properties", QDBusConnection::systemBus(),this); QDBusReply> reply = localeInterface.call("GetAll","org.freedesktop.Accounts.User"); if (reply.isValid()){ QMap propertyMap; propertyMap = reply.value(); if (propertyMap.keys().contains("FormatsLocale")) { formats = propertyMap.find("FormatsLocale").value().toString(); } if(language.isEmpty() && propertyMap.keys().contains("Language")) { language = propertyMap.find("Language").value().toString(); } } else { qDebug() << "reply failed"; } result.append(formats); result.append(language); return result; } void LunarCalendarWidget::initStyle() { //设置样式 QStringList qss; //自定义日控件颜色 QString strSelectType; if (selectType == SelectType_Rect) { strSelectType = "SelectType_Rect"; } else if (selectType == SelectType_Circle) { strSelectType = "SelectType_Circle"; } else if (selectType == SelectType_Triangle) { strSelectType = "SelectType_Triangle"; } else if (selectType == SelectType_Image) { strSelectType = "SelectType_Image"; } //计划去掉qss,保留农历切换的设置 qss.append(QString("LunarCalendarItem{qproperty-showLunar:%1;}").arg(showLunar)); this->setStyleSheet(qss.join("")); } void LunarCalendarWidget::analysisWorktimeJs() { /*解析json文件*/ QFile file("/usr/share/ukui-panel/plugin-calendar/html/jiejiari.js"); file.open(QIODevice::ReadOnly | QIODevice::Text); QString value = file.readAll(); file.close(); QJsonParseError parseJsonErr; QJsonDocument document = QJsonDocument::fromJson(value.toUtf8(),&parseJsonErr); if(!(parseJsonErr.error == QJsonParseError::NoError)) { qDebug()<isHidden()){ widgetYearBody->show(); widgetWeek->hide(); widgetDayBody->hide(); widgetmonthBody->hide(); } else{ widgetYearBody->hide(); widgetWeek->show(); widgetDayBody->show(); widgetmonthBody->hide(); } } void LunarCalendarWidget::monthWidgetChange() { if(widgetmonthBody->isHidden()){ widgetYearBody->hide(); widgetWeek->hide(); widgetDayBody->hide(); widgetmonthBody->show(); } else{ widgetYearBody->hide(); widgetWeek->show(); widgetDayBody->show(); widgetmonthBody->hide(); } } //初始化日期面板 void LunarCalendarWidget::initDate() { int year = date.year(); int month = date.month(); int day = date.day(); if(oneRun) { downLabelHandle(date); yijihandle(date); oneRun = false; } //设置为今天,设置变量防止重复触发 btnClick = true; cboxYearandMonth->setCurrentIndex(cboxYearandMonth->findText(QString("%1.%2").arg(year).arg(month))); btnClick = false; cboxYearandMonthLabel->setText(QString(" %1.%2").arg(year).arg(month)); //首先判断当前月的第一天是星期几 int week = LunarCalendarInfo::Instance()->getFirstDayOfWeek(year, month, FirstdayisSun); //当前月天数 int countDay = LunarCalendarInfo::Instance()->getMonthDays(year, month); //上月天数 int countDayPre = LunarCalendarInfo::Instance()->getMonthDays(1 == month ? year - 1 : year, 1 == month ? 12 : month - 1); //如果上月天数上月刚好一周则另外处理 int startPre, endPre, startNext, endNext, index, tempYear, tempMonth, tempDay; if (0 == week) { startPre = 0; endPre = 7; startNext = 0; endNext = 42 - (countDay + 7); } else { startPre = 0; endPre = week; startNext = week + countDay; endNext = 42; } //纠正1月份前面部分偏差,1月份前面部分是上一年12月份 tempYear = year; tempMonth = month - 1; if (tempMonth < 1) { tempYear--; tempMonth = 12; } //显示上月天数 for (int i = startPre; i < endPre; i++) { index = i; tempDay = countDayPre - endPre + i + 1; QDate date(tempYear, tempMonth, tempDay); QString lunar = LunarCalendarInfo::Instance()->getLunarDay(tempYear, tempMonth, tempDay); dayItems.at(index)->setDate(date, lunar, LunarCalendarItem::DayType_MonthPre); } //纠正12月份后面部分偏差,12月份后面部分是下一年1月份 tempYear = year; tempMonth = month + 1; if (tempMonth > 12) { tempYear++; tempMonth = 1; } //显示下月天数 for (int i = startNext; i < endNext; i++) { index = 42 - endNext + i; tempDay = i - startNext + 1; QDate date(tempYear, tempMonth, tempDay); QString lunar = LunarCalendarInfo::Instance()->getLunarDay(tempYear, tempMonth, tempDay); dayItems.at(index)->setDate(date, lunar, LunarCalendarItem::DayType_MonthNext); } //重新置为当前年月 tempYear = year; tempMonth = month; //显示当前月 for (int i = week; i < (countDay + week); i++) { index = (0 == week ? (i + 7) : i); tempDay = i - week + 1; QDate date(tempYear, tempMonth, tempDay); QString lunar = LunarCalendarInfo::Instance()->getLunarDay(tempYear, tempMonth, tempDay); if (0 == (i % 7) || 6 == (i % 7)) { dayItems.at(index)->setDate(date, lunar, LunarCalendarItem::DayType_WeekEnd); } else { dayItems.at(index)->setDate(date, lunar, LunarCalendarItem::DayType_MonthCurrent); } } for (int i=0;i<12;i++){ yearItems.at(i)->setDate(date.addYears(i)); monthItems.at(i)->setDate(date.addMonths(i)); } } void LunarCalendarWidget::customButtonsClicked(int x) { if (x) { yiLabel->setVisible(true); jiLabel->setVisible(true); yijistate = true; Q_EMIT yijiChangeUp(); } else { yiLabel->setVisible(false); jiLabel->setVisible(false); Q_EMIT yijiChangeDown(); yijistate = false; } } QString LunarCalendarWidget::getSettings() { QString arg = "配置文件"; return arg; } void LunarCalendarWidget::setSettings(QString arg) { } void LunarCalendarWidget::downLabelHandle(const QDate &date) { QString strHoliday; QString strSolarTerms; QString strLunarFestival; QString strLunarYear; QString strLunarMonth; QString strLunarDay; LunarCalendarInfo::Instance()->getLunarCalendarInfo(date.year(), date.month(), date.day(), strHoliday, strSolarTerms, strLunarFestival, strLunarYear, strLunarMonth, strLunarDay); QString labBottomarg = " " + strLunarYear + " " + strLunarMonth + strLunarDay; labBottom->setText(labBottomarg); } void LunarCalendarWidget::yijihandle(const QDate &date) { /*解析json文件*/ QFile file(QString("/usr/share/ukui-panel/plugin-calendar/html/hlnew/hl%1.js").arg(date.year())); file.open(QIODevice::ReadOnly | QIODevice::Text); QString value = file.readAll(); file.close(); QJsonParseError parseJsonErr; QJsonDocument document = QJsonDocument::fromJson(value.toUtf8(),&parseJsonErr); if(!(parseJsonErr.error == QJsonParseError::NoError)) { qDebug()<setText(yiString); jiLabel->setText(jiString); } } void LunarCalendarWidget::yearChanged(const QString &arg1) { //如果是单击按钮切换的日期变动则不需要触发 if (btnClick) { return; } int nIndex = arg1.indexOf("."); if(-1 == nIndex){ return; } int year = arg1.mid(0,nIndex).toInt(); int month = arg1.mid(nIndex + 1).toInt(); int day = date.day(); dateChanged(year, month, day); } void LunarCalendarWidget::monthChanged(const QString &arg1) { //如果是单击按钮切换的日期变动则不需要触发 if (btnClick) { return; } int year = date.year(); int month = arg1.mid(0, arg1.length()).toInt(); int day = date.day(); dateChanged(year, month, day); } void LunarCalendarWidget::clicked(const QDate &date, const LunarCalendarItem::DayType &dayType) { this->date = date; clickDate = date; dayChanged(this->date,clickDate); if (LunarCalendarItem::DayType_MonthPre == dayType) showPreviousMonth(false); else if (LunarCalendarItem::DayType_MonthNext == dayType) showNextMonth(false); } void LunarCalendarWidget::updateYearClicked(const QDate &date, const LunarCalendarYearItem::DayType &dayType) { //通过传来的日期,设置当前年月份 this->date = date; widgetYearBody->hide(); widgetWeek->show(); widgetDayBody->show(); widgetmonthBody->hide(); // qDebug()<<"year:::::::::::::::::::::"<date; // } } void LunarCalendarWidget::updateMonthClicked(const QDate &date, const LunarCalendarMonthItem::DayType &dayType) { //通过传来的日期,设置当前年月份 this->date = date; widgetYearBody->hide(); widgetWeek->show(); widgetDayBody->show(); widgetmonthBody->hide(); qDebug()<setCurrentIndex(cboxYearandMonth->findText(QString("%1.%2").arg(year).arg(month))); btnClick = false; cboxYearandMonthLabel->setText(QString(" %1.%2").arg(year).arg(month)); //首先判断当前月的第一天是星期几 int week = LunarCalendarInfo::Instance()->getFirstDayOfWeek(year, month, FirstdayisSun); //当前月天数 int countDay = LunarCalendarInfo::Instance()->getMonthDays(year, month); //上月天数 int countDayPre = LunarCalendarInfo::Instance()->getMonthDays(1 == month ? year - 1 : year, 1 == month ? 12 : month - 1); //如果上月天数上月刚好一周则另外处理 int startPre, endPre, startNext, endNext, index, tempYear, tempMonth, tempDay; if (0 == week) { startPre = 0; endPre = 7; startNext = 0; endNext = 42 - (countDay + 7); } else { startPre = 0; endPre = week; startNext = week + countDay; endNext = 42; } //纠正1月份前面部分偏差,1月份前面部分是上一年12月份 tempYear = year; tempMonth = month - 1; if (tempMonth < 1) { tempYear--; tempMonth = 12; } //显示上月天数 for (int i = startPre; i < endPre; i++) { index = i; tempDay = countDayPre - endPre + i + 1; QDate date(tempYear, tempMonth, tempDay); QString lunar = LunarCalendarInfo::Instance()->getLunarDay(tempYear, tempMonth, tempDay); dayItems.at(index)->setDate(date, lunar, LunarCalendarItem::DayType_MonthPre); } //纠正12月份后面部分偏差,12月份后面部分是下一年1月份 tempYear = year; tempMonth = month + 1; if (tempMonth > 12) { tempYear++; tempMonth = 1; } //显示下月天数 for (int i = startNext; i < endNext; i++) { index = 42 - endNext + i; tempDay = i - startNext + 1; QDate date(tempYear, tempMonth, tempDay); QString lunar = LunarCalendarInfo::Instance()->getLunarDay(tempYear, tempMonth, tempDay); dayItems.at(index)->setDate(date, lunar, LunarCalendarItem::DayType_MonthNext); } //重新置为当前年月 tempYear = year; tempMonth = month; //显示当前月 for (int i = week; i < (countDay + week); i++) { index = (0 == week ? (i + 7) : i); tempDay = i - week + 1; QDate date(tempYear, tempMonth, tempDay); QString lunar = LunarCalendarInfo::Instance()->getLunarDay(tempYear, tempMonth, tempDay); if (0 == (i % 7) || 6 == (i % 7)) { dayItems.at(index)->setDate(date, lunar, LunarCalendarItem::DayType_WeekEnd); } else { dayItems.at(index)->setDate(date, lunar, LunarCalendarItem::DayType_MonthCurrent); } } for (int i=0;i<12;i++){ yearItems.at(i)->setDate(clickDate.addYears(i)); // qDebug()<<"*******************"<<"循环位:"<setDate(clickDate.addMonths(i)); } } void LunarCalendarWidget::dayChanged(const QDate &date,const QDate &m_date) { //计算星期几,当前天对应标签索引=日期+星期几-1 int year = date.year(); int month = date.month(); int day = date.day(); int week = LunarCalendarInfo::Instance()->getFirstDayOfWeek(year, month, FirstdayisSun); //选中当前日期,其他日期恢复,这里还有优化空间,比方说类似单选框机制 for (int i = 0; i < 42; i++) { //当月第一天是星期天要另外计算 int index = day + week - 1; if (week == 0) { index = day + 6; } dayItems.at(i)->setSelect(false); if(dayItems.at(i)->getDate() == m_date) { dayItems.at(i)->setSelect(i == index); } if (i == index) { downLabelHandle(dayItems.at(i)->getDate()); yijihandle(dayItems.at(i)->getDate()); } } //发送日期单击信号 Q_EMIT clicked(date); //发送日期更新信号 Q_EMIT selectionChanged(); } void LunarCalendarWidget::dateChanged(int year, int month, int day) { //如果原有天大于28则设置为1,防止出错 date.setDate(year, month, day > 28 ? 1 : day); initDate(); } LunarCalendarWidget::CalendarStyle LunarCalendarWidget::getCalendarStyle() const { return this->calendarStyle; } QDate LunarCalendarWidget::getDate() const { return this->date; } QColor LunarCalendarWidget::getWeekTextColor() const { return this->weekTextColor; } QColor LunarCalendarWidget::getWeekBgColor() const { return this->weekBgColor; } bool LunarCalendarWidget::getShowLunar() const { return this->showLunar; } QString LunarCalendarWidget::getBgImage() const { return this->bgImage; } LunarCalendarWidget::SelectType LunarCalendarWidget::getSelectType() const { return this->selectType; } QColor LunarCalendarWidget::getBorderColor() const { return this->borderColor; } QColor LunarCalendarWidget::getWeekColor() const { return this->weekColor; } QColor LunarCalendarWidget::getSuperColor() const { return this->superColor; } QColor LunarCalendarWidget::getLunarColor() const { return this->lunarColor; } QColor LunarCalendarWidget::getCurrentTextColor() const { return this->currentTextColor; } QColor LunarCalendarWidget::getOtherTextColor() const { return this->otherTextColor; } QColor LunarCalendarWidget::getSelectTextColor() const { return this->selectTextColor; } QColor LunarCalendarWidget::getHoverTextColor() const { return this->hoverTextColor; } QColor LunarCalendarWidget::getCurrentLunarColor() const { return this->currentLunarColor; } QColor LunarCalendarWidget::getOtherLunarColor() const { return this->otherLunarColor; } QColor LunarCalendarWidget::getSelectLunarColor() const { return this->selectLunarColor; } QColor LunarCalendarWidget::getHoverLunarColor() const { return this->hoverLunarColor; } QColor LunarCalendarWidget::getCurrentBgColor() const { return this->currentBgColor; } QColor LunarCalendarWidget::getOtherBgColor() const { return this->otherBgColor; } QColor LunarCalendarWidget::getSelectBgColor() const { return this->selectBgColor; } QColor LunarCalendarWidget::getHoverBgColor() const { return this->hoverBgColor; } QSize LunarCalendarWidget::sizeHint() const { return QSize(600, 500); } QSize LunarCalendarWidget::minimumSizeHint() const { return QSize(200, 150); } //显示上一年 void LunarCalendarWidget::showPreviousYear() { int year = date.year(); int month = date.month(); int day = date.day(); if (year <= 1901) { return; } year--; dateChanged(year, month, day); } //显示下一年 void LunarCalendarWidget::showNextYear() { int year = date.year(); int month = date.month(); int day = date.day(); if (year >= 2099) { return; } year++; dateChanged(year, month, day); } //显示上月日期 void LunarCalendarWidget::showPreviousMonth(bool date_clicked) { int year = date.year(); int month = date.month(); int day = date.day(); if (year <= 1901 && month == 1) { return; } //extra: if (date_clicked) month--; if (month < 1) { month = 12; year--; } dateChanged(year, month, day); // dayChanged(this->date,clickDate); } //显示下月日期 void LunarCalendarWidget::showNextMonth(bool date_clicked) { int year = date.year(); int month = date.month(); int day = date.day(); if (year >= 2099 ) { return; } //extra if (date_clicked)month++; if (month > 12) { month = 1; year++; } dateChanged(year, month, day); //dayChanged(this->date,clickDate); } //转到今天 void LunarCalendarWidget::showToday() { widgetYearBody->hide(); widgetmonthBody->hide(); widgetDayBody->show(); widgetWeek->show(); date = QDate::currentDate(); initDate(); dayChanged(this->date,clickDate); } void LunarCalendarWidget::setCalendarStyle(const LunarCalendarWidget::CalendarStyle &calendarStyle) { if (this->calendarStyle != calendarStyle) { this->calendarStyle = calendarStyle; } } void LunarCalendarWidget::setWeekNameFormat(bool FirstDayisSun) { FirstdayisSun = FirstDayisSun; setLocaleCalendar();//在设置是从某星期作为起点时,再判断某区域下日历的显示 initDate(); } void LunarCalendarWidget::setDate(const QDate &date) { if (this->date != date) { this->date = date; initDate(); } } void LunarCalendarWidget::setWeekTextColor(const QColor &weekTextColor) { if (this->weekTextColor != weekTextColor) { this->weekTextColor = weekTextColor; initStyle(); } } void LunarCalendarWidget::setWeekBgColor(const QColor &weekBgColor) { if (this->weekBgColor != weekBgColor) { this->weekBgColor = weekBgColor; initStyle(); } } void LunarCalendarWidget::setShowLunar(bool showLunar) { if(calendar_gsettings!=nullptr){ if (locale == "zh_CN"){ qDebug()<<"中文模式"; showLunar = calendar_gsettings->get(LUNAR_KEY).toString() == "lunar"; }else if (locale == "en_US"){ qDebug()<<"英文模式"; showLunar = false; } } this->showLunar = showLunar; initStyle(); } void LunarCalendarWidget::setBgImage(const QString &bgImage) { if (this->bgImage != bgImage) { this->bgImage = bgImage; initStyle(); } } void LunarCalendarWidget::setSelectType(const LunarCalendarWidget::SelectType &selectType) { if (this->selectType != selectType) { this->selectType = selectType; initStyle(); } } void LunarCalendarWidget::setBorderColor(const QColor &borderColor) { if (this->borderColor != borderColor) { this->borderColor = borderColor; initStyle(); } } void LunarCalendarWidget::setWeekColor(const QColor &weekColor) { if (this->weekColor != weekColor) { this->weekColor = weekColor; initStyle(); } } void LunarCalendarWidget::setSuperColor(const QColor &superColor) { if (this->superColor != superColor) { this->superColor = superColor; initStyle(); } } void LunarCalendarWidget::setLunarColor(const QColor &lunarColor) { if (this->lunarColor != lunarColor) { this->lunarColor = lunarColor; initStyle(); } } void LunarCalendarWidget::setCurrentTextColor(const QColor ¤tTextColor) { if (this->currentTextColor != currentTextColor) { this->currentTextColor = currentTextColor; initStyle(); } } void LunarCalendarWidget::setOtherTextColor(const QColor &otherTextColor) { if (this->otherTextColor != otherTextColor) { this->otherTextColor = otherTextColor; initStyle(); } } void LunarCalendarWidget::setSelectTextColor(const QColor &selectTextColor) { if (this->selectTextColor != selectTextColor) { this->selectTextColor = selectTextColor; initStyle(); } } void LunarCalendarWidget::setHoverTextColor(const QColor &hoverTextColor) { if (this->hoverTextColor != hoverTextColor) { this->hoverTextColor = hoverTextColor; initStyle(); } } void LunarCalendarWidget::setCurrentLunarColor(const QColor ¤tLunarColor) { if (this->currentLunarColor != currentLunarColor) { this->currentLunarColor = currentLunarColor; initStyle(); } } void LunarCalendarWidget::setOtherLunarColor(const QColor &otherLunarColor) { if (this->otherLunarColor != otherLunarColor) { this->otherLunarColor = otherLunarColor; initStyle(); } } void LunarCalendarWidget::setSelectLunarColor(const QColor &selectLunarColor) { if (this->selectLunarColor != selectLunarColor) { this->selectLunarColor = selectLunarColor; initStyle(); } } void LunarCalendarWidget::setHoverLunarColor(const QColor &hoverLunarColor) { if (this->hoverLunarColor != hoverLunarColor) { this->hoverLunarColor = hoverLunarColor; initStyle(); } } void LunarCalendarWidget::setCurrentBgColor(const QColor ¤tBgColor) { if (this->currentBgColor != currentBgColor) { this->currentBgColor = currentBgColor; initStyle(); } } void LunarCalendarWidget::setOtherBgColor(const QColor &otherBgColor) { if (this->otherBgColor != otherBgColor) { this->otherBgColor = otherBgColor; initStyle(); } } void LunarCalendarWidget::setSelectBgColor(const QColor &selectBgColor) { if (this->selectBgColor != selectBgColor) { this->selectBgColor = selectBgColor; initStyle(); } } void LunarCalendarWidget::setHoverBgColor(const QColor &hoverBgColor) { if (this->hoverBgColor != hoverBgColor) { this->hoverBgColor = hoverBgColor; initStyle(); } } void LunarCalendarWidget::wheelEvent(QWheelEvent *event) { if (event->delta() > 0) showPreviousMonth(); else showNextMonth(); } m_PartLineWidget::m_PartLineWidget(QWidget *parent) : QWidget(parent) { } void m_PartLineWidget::paintEvent(QPaintEvent *event) { QPainter p(this); QRect rect = this->rect(); p.setRenderHint(QPainter::Antialiasing); // 反锯齿; QColor color=qApp->palette().color(QPalette::Base); if(color.red() == 255 && color.green() == 255 && color.blue() == 255){ color.setRgb(1,1,1,255); } else if (color.red() == 31 && color.green() == 32 && color.blue() == 34) { color.setRgb(255,255,255,255); } p.setBrush(color); p.setOpacity(0.05); p.setPen(Qt::NoPen); p.drawRoundedRect(rect,0,0); QWidget::paintEvent(event); } statelabel::statelabel() : QLabel() { } //鼠标点击事件 void statelabel::mousePressEvent(QMouseEvent *event) { if (event->buttons() == Qt::LeftButton){ Q_EMIT labelclick(); } return; } ukui-panel-3.0.6.4/plugin-calendar/lunarcalendarwidget/lunarcalendaritem.cpp0000644000175000017500000005032514203402514025636 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see LunarCalendarItem::LunarCalendarItem(QWidget *parent) : QWidget(parent) { hover = false; pressed = false; select = false; showLunar = true; bgImage = ":/image/bg_calendar.png"; selectType = SelectType_Rect; date = QDate::currentDate(); lunar = "初一"; dayType = DayType_MonthCurrent; //实时监听主题变化 const QByteArray id("org.ukui.style"); QGSettings * fontSetting = new QGSettings(id, QByteArray(), this); connect(fontSetting, &QGSettings::changed,[=](QString key) { if(fontSetting->get("style-name").toString() == "ukui-default") { weekColor = QColor(255, 255, 255); currentTextColor = QColor(255, 255, 255); otherTextColor = QColor(255, 255, 255,40); otherLunarColor = QColor(255, 255, 255,40); currentLunarColor = QColor(255, 255, 255,90); lunarColor = QColor(255, 255, 255,90); } else if(fontSetting->get("style-name").toString() == "ukui-light") { weekColor = QColor(0, 0, 0); currentTextColor = QColor(0, 0, 0); otherTextColor = QColor(0,0,0,40); otherLunarColor = QColor(0,0,0,40); currentLunarColor = QColor(0,0,0,90); lunarColor = QColor(0,0,0,90); } else if(fontSetting->get("style-name").toString() == "ukui-dark") { weekColor = QColor(255, 255, 255); currentTextColor = QColor(255, 255, 255); otherTextColor = QColor(255, 255, 255,40); otherLunarColor = QColor(255, 255, 255,40); currentLunarColor = QColor(255, 255, 255,90); lunarColor = QColor(255, 255, 255,90); } }); if(fontSetting->get("style-name").toString() == "ukui-light") { weekColor = QColor(0, 0, 0); currentTextColor = QColor(0, 0, 0); otherTextColor = QColor(0,0,0,40); otherLunarColor = QColor(0,0,0,40); currentLunarColor = QColor(0,0,0,90); lunarColor = QColor(0,0,0,90); } else { weekColor = QColor(255, 255, 255); currentTextColor = QColor(255, 255, 255); otherTextColor = QColor(255, 255, 255,40); otherLunarColor = QColor(255, 255, 255,40); currentLunarColor = QColor(255, 255, 255,90); lunarColor = QColor(255, 255, 255,90); } borderColor = QColor(180, 180, 180); superColor = QColor(255, 129, 6); selectTextColor = QColor(255, 255, 255); hoverTextColor = QColor(250, 250, 250); selectLunarColor = QColor(255, 255, 255); hoverLunarColor = QColor(250, 250, 250); currentBgColor = QColor(255, 255, 255); otherBgColor = QColor(240, 240, 240); selectBgColor = QColor(55,144,250); hoverBgColor = QColor(204, 183, 180); } void LunarCalendarItem::enterEvent(QEvent *) { hover = true; this->update(); } void LunarCalendarItem::leaveEvent(QEvent *) { hover = false; this->update(); } void LunarCalendarItem::mousePressEvent(QMouseEvent *) { pressed = true; this->update(); Q_EMIT clicked(date, dayType); } void LunarCalendarItem::mouseReleaseEvent(QMouseEvent *) { pressed = false; this->update(); } QString LunarCalendarItem::handleJsMap(QString year,QString month2day) { QString oneNUmber = "worktime.y" + year; QString twoNumber = "d" + month2day; QMap>::Iterator it = worktime.begin(); while(it!=worktime.end()) { if(it.key() == oneNUmber) { QMap::Iterator it1 = it.value().begin(); while(it1!=it.value().end()) { if(it1.key() == twoNumber) { return it1.value(); } it1++; } } it++; } return "-1"; } void LunarCalendarItem::paintEvent(QPaintEvent *) { QDate dateNow = QDate::currentDate(); //绘制准备工作,启用反锯齿 QPainter painter(this); painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing); //绘制背景和边框 drawBg(&painter); //对比当前的时间,画选中状态 if(dateNow == date) { drawBgCurrent(&painter, selectBgColor); } //绘制悬停状态 if (hover) { drawBgHover(&painter, hoverBgColor); } //绘制选中状态 if (select) { drawBgHover(&painter, hoverBgColor); } //绘制日期 drawDay(&painter); //绘制农历信息 drawLunar(&painter); } void LunarCalendarItem::drawBg(QPainter *painter) { painter->save(); //根据当前类型选择对应的颜色 QColor bgColor = currentBgColor; if (dayType == DayType_MonthPre || dayType == DayType_MonthNext) { bgColor = otherBgColor; } //painter->setPen(borderColor); //painter->setBrush(bgColor); //painter->drawRect(rect()); painter->restore(); } void LunarCalendarItem::drawBgCurrent(QPainter *painter, const QColor &color) { painter->save(); painter->setPen(Qt::NoPen); painter->setBrush(color); QRect rect = this->rect(); painter->drawRoundedRect(rect,4,4); // //根据设定绘制背景样式 // if (selectType == SelectType_Rect) { // } painter->restore(); } void LunarCalendarItem::drawBgHover(QPainter *painter, const QColor &color) { painter->save(); QRect rect = this->rect(); painter->setPen(QPen(QColor(55,143,250),2)); painter->drawRoundedRect(rect,4,4); // //根据设定绘制背景样式 // if (selectType == SelectType_Rect) { // } painter->restore(); } void LunarCalendarItem::drawDay(QPainter *painter) { int width = this->width(); int height = this->height(); int side = qMin(width, height); painter->save(); //根据当前类型选择对应的颜色 QColor color = currentTextColor; if (dayType == DayType_MonthPre || dayType == DayType_MonthNext) { color = otherTextColor; } else if (dayType == DayType_WeekEnd) { color = weekColor; } /* if (select) { color = selectTextColor; } *//*else if (hover) { color = hoverTextColor; }*/ painter->setPen(color); QFont font; font.setPixelSize(side * 0.3); //设置文字粗细 font.setBold(true); painter->setFont(font); QLocale locale = (QLocale::system().name() == "zh_CN" ? (QLocale::Chinese) : (QLocale::English)); //代码复用率待优化 if (showLunar) { QRect dayRect = QRect(0, 0, width, height / 1.7); painter->drawText(dayRect, Qt::AlignHCenter | Qt::AlignBottom, QString::number(date.day())); if (handleJsMap(date.toString("yyyy"),date.toString("MMdd")) == "2") { painter->setPen(Qt::NoPen); if(locale == QLocale::Chinese){ painter->setBrush(QColor(244,78,80)); } QRect dayRect1 = QRect(0, 0, width/3.5,height/3.5); painter->drawRoundedRect(dayRect1,1,1); font.setPixelSize(side / 5); painter->setFont(font); painter->setPen(Qt::white); if(locale == QLocale::Chinese){ painter->drawText(dayRect1, Qt::AlignHCenter | Qt::AlignBottom,"休"); } } else if (handleJsMap(date.toString("yyyy"),date.toString("MMdd")) == "1") { painter->setPen(Qt::NoPen); if(locale == QLocale::Chinese){ painter->setBrush(QColor(251,170,42)); } QRect dayRect1 = QRect(0, 0, width/3.5,height/3.5); painter->drawRoundedRect(dayRect1,1,1); font.setPixelSize(side / 5); painter->setFont(font); painter->setPen(Qt::white); if(locale == QLocale::Chinese){ painter->drawText(dayRect1, Qt::AlignHCenter | Qt::AlignBottom,"班"); } } } else { //非农历 QRect dayRect = QRect(0, 0, width, height); painter->drawText(dayRect, Qt::AlignCenter, QString::number(date.day())); if (handleJsMap(date.toString("yyyy"),date.toString("MMdd")) == "2") { painter->setPen(Qt::NoPen); // painter->setBrush(QColor(255,0,0)); QRect dayRect1 = QRect(0, 0, width/3.5,height/3.5); painter->drawRoundedRect(dayRect1,1,1); font.setPixelSize(side / 5); painter->setFont(font); painter->setPen(Qt::white); // painter->drawText(dayRect1, Qt::AlignHCenter | Qt::AlignBottom,"休"); } else if (handleJsMap(date.toString("yyyy"),date.toString("MMdd")) == "1") { painter->setPen(Qt::NoPen); // painter->setBrush(QColor(251,170,42)); QRect dayRect1 = QRect(0, 0, width/3.5,height/3.5); painter->drawRoundedRect(dayRect1,1,1); font.setPixelSize(side / 5); painter->setFont(font); painter->setPen(Qt::white); // painter->drawText(dayRect1, Qt::AlignHCenter | Qt::AlignBottom,"班"); } } painter->restore(); } void LunarCalendarItem::drawLunar(QPainter *painter) { int width = this->width(); int height = this->height(); int side = qMin(width, height); int month; int day; QString strHoliday; QLocale locale = (QLocale::system().name() == "zh_CN" ? (QLocale::Chinese) : (QLocale::English)); qDebug()<<"LunarCalendarItem语言模式:"<save(); if (!showLunar) { //非农历 // int month = date.month(); // int day = date.day(); // LunarCalendarInfo *lun = LunarCalendarInfo::Instance(); // strHoliday = lun->getHoliday(month,day); //// delete lun; // QColor color = currentLunarColor; // if (dayType == DayType_MonthPre || dayType == DayType_MonthNext) { // color = otherLunarColor; // } // painter->setPen(color); // QFont font; // font.setPixelSize(side * 0.27); // painter->setFont(font); // QRect lunarRect(0, height / 2, width, height / 2); // painter->drawText(lunarRect, Qt::AlignCenter, strHoliday); } else { if(locale == QLocale::Chinese){ QStringList listDayName; listDayName << "*" << "初一" << "初二" << "初三" << "初四" << "初五" << "初六" << "初七" << "初八" << "初九" << "初十" << "十一" << "十二" << "十三" << "十四" << "十五" << "十六" << "十七" << "十八" << "十九" << "二十" << "廿一" << "廿二" << "廿三" << "廿四" << "廿五" << "廿六" << "廿七" << "廿八" << "廿九" << "三十"; //判断当前农历文字是否节日,是节日且是当月则用农历节日颜色显示 bool exist = (!listDayName.contains(lunar) && dayType != DayType_MonthPre && dayType != DayType_MonthNext); //根据当前类型选择对应的颜色 QColor color = currentLunarColor; if (dayType == DayType_MonthPre || dayType == DayType_MonthNext) { color = otherLunarColor; } // if (select) { // color = selectTextColor; // } /*else if (hover) { // color = hoverTextColor; // }*/ else if (exist) { // color = lunarColor; // } if (exist) { color = lunarColor; } painter->setPen(color); QFont font; font.setPixelSize(side * 0.27); painter->setFont(font); QRect lunarRect(0, height / 2, width, height / 2); painter->drawText(lunarRect, Qt::AlignCenter, lunar); } painter->restore(); } } bool LunarCalendarItem::getSelect() const { return this->select; } bool LunarCalendarItem::getShowLunar() const { return this->showLunar; } QString LunarCalendarItem::getBgImage() const { return this->bgImage; } LunarCalendarItem::SelectType LunarCalendarItem::getSelectType() const { return this->selectType; } QDate LunarCalendarItem::getDate() const { return this->date; } QString LunarCalendarItem::getLunar() const { return this->lunar; } LunarCalendarItem::DayType LunarCalendarItem::getDayType() const { return this->dayType; } QColor LunarCalendarItem::getBorderColor() const { return this->borderColor; } QColor LunarCalendarItem::getWeekColor() const { return this->weekColor; } QColor LunarCalendarItem::getSuperColor() const { return this->superColor; } QColor LunarCalendarItem::getLunarColor() const { return this->lunarColor; } QColor LunarCalendarItem::getCurrentTextColor() const { return this->currentTextColor; } QColor LunarCalendarItem::getOtherTextColor() const { return this->otherTextColor; } QColor LunarCalendarItem::getSelectTextColor() const { return this->selectTextColor; } QColor LunarCalendarItem::getHoverTextColor() const { return this->hoverTextColor; } QColor LunarCalendarItem::getCurrentLunarColor() const { return this->currentLunarColor; } QColor LunarCalendarItem::getOtherLunarColor() const { return this->otherLunarColor; } QColor LunarCalendarItem::getSelectLunarColor() const { return this->selectLunarColor; } QColor LunarCalendarItem::getHoverLunarColor() const { return this->hoverLunarColor; } QColor LunarCalendarItem::getCurrentBgColor() const { return this->currentBgColor; } QColor LunarCalendarItem::getOtherBgColor() const { return this->otherBgColor; } QColor LunarCalendarItem::getSelectBgColor() const { return this->selectBgColor; } QColor LunarCalendarItem::getHoverBgColor() const { return this->hoverBgColor; } QSize LunarCalendarItem::sizeHint() const { return QSize(100, 100); } QSize LunarCalendarItem::minimumSizeHint() const { return QSize(20, 20); } void LunarCalendarItem::setSelect(bool select) { if (this->select != select) { this->select = select; this->update(); } } void LunarCalendarItem::setShowLunar(bool showLunar) { this->showLunar = showLunar; this->update(); } void LunarCalendarItem::setBgImage(const QString &bgImage) { if (this->bgImage != bgImage) { this->bgImage = bgImage; this->update(); } } void LunarCalendarItem::setSelectType(const LunarCalendarItem::SelectType &selectType) { if (this->selectType != selectType) { this->selectType = selectType; this->update(); } } void LunarCalendarItem::setDate(const QDate &date) { if (this->date != date) { this->date = date; this->update(); } } void LunarCalendarItem::setLunar(const QString &lunar) { if (this->lunar != lunar) { this->lunar = lunar; this->update(); } } void LunarCalendarItem::setDayType(const LunarCalendarItem::DayType &dayType) { if (this->dayType != dayType) { this->dayType = dayType; this->update(); } } void LunarCalendarItem::setDate(const QDate &date, const QString &lunar, const DayType &dayType) { this->date = date; this->lunar = lunar; this->dayType = dayType; this->update(); } void LunarCalendarItem::setBorderColor(const QColor &borderColor) { if (this->borderColor != borderColor) { this->borderColor = borderColor; this->update(); } } void LunarCalendarItem::setWeekColor(const QColor &weekColor) { if (this->weekColor != weekColor) { this->weekColor = weekColor; this->update(); } } void LunarCalendarItem::setSuperColor(const QColor &superColor) { if (this->superColor != superColor) { this->superColor = superColor; this->update(); } } void LunarCalendarItem::setLunarColor(const QColor &lunarColor) { if (this->lunarColor != lunarColor) { this->lunarColor = lunarColor; this->update(); } } void LunarCalendarItem::setCurrentTextColor(const QColor ¤tTextColor) { if (this->currentTextColor != currentTextColor) { this->currentTextColor = currentTextColor; this->update(); } } void LunarCalendarItem::setOtherTextColor(const QColor &otherTextColor) { if (this->otherTextColor != otherTextColor) { this->otherTextColor = otherTextColor; this->update(); } } void LunarCalendarItem::setSelectTextColor(const QColor &selectTextColor) { if (this->selectTextColor != selectTextColor) { this->selectTextColor = selectTextColor; this->update(); } } void LunarCalendarItem::setHoverTextColor(const QColor &hoverTextColor) { if (this->hoverTextColor != hoverTextColor) { this->hoverTextColor = hoverTextColor; this->update(); } } void LunarCalendarItem::setCurrentLunarColor(const QColor ¤tLunarColor) { if (this->currentLunarColor != currentLunarColor) { this->currentLunarColor = currentLunarColor; this->update(); } } void LunarCalendarItem::setOtherLunarColor(const QColor &otherLunarColor) { if (this->otherLunarColor != otherLunarColor) { this->otherLunarColor = otherLunarColor; this->update(); } } void LunarCalendarItem::setSelectLunarColor(const QColor &selectLunarColor) { if (this->selectLunarColor != selectLunarColor) { this->selectLunarColor = selectLunarColor; this->update(); } } void LunarCalendarItem::setHoverLunarColor(const QColor &hoverLunarColor) { if (this->hoverLunarColor != hoverLunarColor) { this->hoverLunarColor = hoverLunarColor; this->update(); } } void LunarCalendarItem::setCurrentBgColor(const QColor ¤tBgColor) { if (this->currentBgColor != currentBgColor) { this->currentBgColor = currentBgColor; this->update(); } } void LunarCalendarItem::setOtherBgColor(const QColor &otherBgColor) { if (this->otherBgColor != otherBgColor) { this->otherBgColor = otherBgColor; this->update(); } } void LunarCalendarItem::setSelectBgColor(const QColor &selectBgColor) { if (this->selectBgColor != selectBgColor) { this->selectBgColor = selectBgColor; this->update(); } } void LunarCalendarItem::setHoverBgColor(const QColor &hoverBgColor) { if (this->hoverBgColor != hoverBgColor) { this->hoverBgColor = hoverBgColor; this->update(); } } bool LunarCalendarItem::event(QEvent *event) { if(event->type()==QEvent::ToolTip){ if(date.month()==11 && date.day()==9 ){ setToolTip(tr("消防宣传日")); } if(date.month()==3 && date.day()==5 ){ setToolTip(tr("志愿者服务日")); } if(date.month()==6 && date.day()==6 ){ setToolTip(tr("全国爱眼日")); } if(date.month()==7 && date.day()==7 ){ setToolTip(tr("抗战纪念日")); } } return QWidget::event(event); } ukui-panel-3.0.6.4/plugin-calendar/lunarcalendarwidget/frmlunarcalendarwidget.cpp0000644000175000017500000001305214203402514026664 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #define TRANSPARENCY_SETTINGS "org.ukui.control-center.personalise" #define TRANSPARENCY_KEY "transparency" #define PANEL_CONTROL_IN_CALENDAR "org.ukui.control-center.panel.plugins" #define LUNAR_KEY "calendar" #define FIRST_DAY_KEY "firstday" frmLunarCalendarWidget::frmLunarCalendarWidget(QWidget *parent) : QWidget(parent), ui(new Ui::frmLunarCalendarWidget) { installEventFilter(this); ui->setupUi(this); connect(ui->lunarCalendarWidget,&LunarCalendarWidget::yijiChangeUp,this,&frmLunarCalendarWidget::changeUpSize); connect(ui->lunarCalendarWidget,&LunarCalendarWidget::yijiChangeDown,this,&frmLunarCalendarWidget::changeDownSize); this->initForm(); this->setWindowFlags(Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint);//去掉标题栏 // this->setWindowFlags(Qt::Popup); setAttribute(Qt::WA_TranslucentBackground);//设置窗口背景透明 setProperty("useSystemStyleBlur", true); this->setFixedSize(440, 600); const QByteArray transparency_id(TRANSPARENCY_SETTINGS); if(QGSettings::isSchemaInstalled(transparency_id)){ transparency_gsettings = new QGSettings(transparency_id); } const QByteArray calendar_id(PANEL_CONTROL_IN_CALENDAR); if(QGSettings::isSchemaInstalled(calendar_id)){ calendar_gsettings = new QGSettings(calendar_id); //公历/农历切换 connect(calendar_gsettings, &QGSettings::changed, this, [=] (const QString &key){ if(key == LUNAR_KEY){ ckShowLunar_stateChanged(calendar_gsettings->get(LUNAR_KEY).toString() == "lunar"); } if (key == FIRST_DAY_KEY) { cboxWeekNameFormat_currentIndexChanged(calendar_gsettings->get(FIRST_DAY_KEY).toString() == "sunday"); } }); } else { ckShowLunar_stateChanged(false); cboxWeekNameFormat_currentIndexChanged(false); } } frmLunarCalendarWidget::~frmLunarCalendarWidget() { delete ui; } void frmLunarCalendarWidget::changeUpSize() { this->setFixedSize(440, 652); Q_EMIT yijiChangeUp(); } void frmLunarCalendarWidget::changeDownSize() { this->setFixedSize(440, 600); Q_EMIT yijiChangeDown(); } void frmLunarCalendarWidget::initForm() { //ui->cboxWeekNameFormat->setCurrentIndex(0); } void frmLunarCalendarWidget::cboxCalendarStyle_currentIndexChanged(int index) { ui->lunarCalendarWidget->setCalendarStyle((LunarCalendarWidget::CalendarStyle)index); } void frmLunarCalendarWidget::cboxSelectType_currentIndexChanged(int index) { ui->lunarCalendarWidget->setSelectType((LunarCalendarWidget::SelectType)index); } void frmLunarCalendarWidget::cboxWeekNameFormat_currentIndexChanged(bool FirstDayisSun) { ui->lunarCalendarWidget->setWeekNameFormat(FirstDayisSun); } void frmLunarCalendarWidget::ckShowLunar_stateChanged(bool arg1) { ui->lunarCalendarWidget->setShowLunar(arg1); } void frmLunarCalendarWidget::paintEvent(QPaintEvent *) { QStyleOption opt; opt.init(this); QRect rect = this->rect(); QPainter p(this); double tran =1; const QByteArray transparency_id(TRANSPARENCY_SETTINGS); if(QGSettings::isSchemaInstalled(transparency_id)){ tran=transparency_gsettings->get(TRANSPARENCY_KEY).toDouble()*255; } QColor color = palette().color(QPalette::Base); color.setAlpha(tran); QBrush brush =QBrush(color); p.setBrush(brush); p.setPen(Qt::NoPen); p.setRenderHint(QPainter::Antialiasing); p.drawRoundedRect(rect,6,6); style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); } /* * 事件过滤,检测鼠标点击外部活动区域则收回收纳栏 */ bool frmLunarCalendarWidget::eventFilter(QObject *obj, QEvent *event) { if (obj == this) { if (event->type() == QEvent::MouseButtonPress) { QMouseEvent *mouseEvent = static_cast(event); if (mouseEvent->button() == Qt::LeftButton) { // this->hide(); // status=ST_HIDE; return true; } else if(mouseEvent->button() == Qt::RightButton) { return true; } } else if(event->type() == QEvent::ContextMenu) { return false; } else if (event->type() == QEvent::WindowDeactivate) { //qDebug()<<"激活外部窗口"; this->hide(); return true; } else if (event->type() == QEvent::StyleChange) { } } if (!isActiveWindow()) { activateWindow(); } return false; } ukui-panel-3.0.6.4/plugin-calendar/lunarcalendarwidget/lunarcalendaryearitem.cpp0000644000175000017500000003047514203402514026523 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see LunarCalendarYearItem::LunarCalendarYearItem(QWidget *parent) : QWidget(parent) { hover = false; pressed = false; select = false; showLunar = true; bgImage = ":/image/bg_calendar.png"; selectType = SelectType_Rect; date = QDate::currentDate(); lunar = "初一"; dayType = DayType_MonthCurrent; //实时监听主题变化 const QByteArray id("org.ukui.style"); QGSettings * fontSetting = new QGSettings(id, QByteArray(), this); connect(fontSetting, &QGSettings::changed,[=](QString key) { if(fontSetting->get("style-name").toString() == "ukui-default") { weekColor = QColor(255, 255, 255); currentTextColor = QColor(255, 255, 255); otherTextColor = QColor(255, 255, 255,40); otherLunarColor = QColor(255, 255, 255,40); currentLunarColor = QColor(255, 255, 255,90); lunarColor = QColor(255, 255, 255,90); } else if(fontSetting->get("style-name").toString() == "ukui-light") { weekColor = QColor(0, 0, 0); currentTextColor = QColor(0, 0, 0); otherTextColor = QColor(0,0,0,40); otherLunarColor = QColor(0,0,0,40); currentLunarColor = QColor(0,0,0,90); lunarColor = QColor(0,0,0,90); } else if(fontSetting->get("style-name").toString() == "ukui-dark") { weekColor = QColor(255, 255, 255); currentTextColor = QColor(255, 255, 255); otherTextColor = QColor(255, 255, 255,40); otherLunarColor = QColor(255, 255, 255,40); currentLunarColor = QColor(255, 255, 255,90); lunarColor = QColor(255, 255, 255,90); } }); if(fontSetting->get("style-name").toString() == "ukui-light") { weekColor = QColor(0, 0, 0); currentTextColor = QColor(0, 0, 0); otherTextColor = QColor(0,0,0,40); otherLunarColor = QColor(0,0,0,40); currentLunarColor = QColor(0,0,0,90); lunarColor = QColor(0,0,0,90); } else { weekColor = QColor(255, 255, 255); currentTextColor = QColor(255, 255, 255); otherTextColor = QColor(255, 255, 255,40); otherLunarColor = QColor(255, 255, 255,40); currentLunarColor = QColor(255, 255, 255,90); lunarColor = QColor(255, 255, 255,90); } borderColor = QColor(180, 180, 180); superColor = QColor(255, 129, 6); selectTextColor = QColor(255, 255, 255); hoverTextColor = QColor(250, 250, 250); selectLunarColor = QColor(255, 255, 255); hoverLunarColor = QColor(250, 250, 250); currentBgColor = QColor(255, 255, 255); otherBgColor = QColor(240, 240, 240); selectBgColor = QColor(55,144,250); hoverBgColor = QColor(204, 183, 180); } void LunarCalendarYearItem::enterEvent(QEvent *) { hover = true; this->update(); } void LunarCalendarYearItem::leaveEvent(QEvent *) { hover = false; this->update(); } void LunarCalendarYearItem::mousePressEvent(QMouseEvent *) { pressed = true; this->update(); // Q_EMIT clicked(date, dayType); Q_EMIT yearMessage(date, dayType); } void LunarCalendarYearItem::mouseReleaseEvent(QMouseEvent *) { pressed = false; this->update(); } void LunarCalendarYearItem::paintEvent(QPaintEvent *) { QDate dateNow = QDate::currentDate(); //绘制准备工作,启用反锯齿 QPainter painter(this); painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing); //绘制背景和边框 drawBg(&painter); //对比当前的时间,画选中状态 if(dateNow.year() == date.year()) { drawBgCurrent(&painter, selectBgColor); } //绘制悬停状态 if (hover) { drawBgHover(&painter, hoverBgColor); } //绘制选中状态 if (select) { drawBgHover(&painter, hoverBgColor); } //绘制日期 drawYear(&painter); } void LunarCalendarYearItem::drawBg(QPainter *painter) { painter->save(); //根据当前类型选择对应的颜色 QColor bgColor = currentBgColor; if (dayType == DayType_MonthPre || dayType == DayType_MonthNext) { bgColor = otherBgColor; } painter->restore(); } void LunarCalendarYearItem::drawBgCurrent(QPainter *painter, const QColor &color) { painter->save(); painter->setPen(Qt::NoPen); painter->setBrush(color); QRect rect = this->rect(); painter->drawRoundedRect(rect,4,4); painter->restore(); } void LunarCalendarYearItem::drawBgHover(QPainter *painter, const QColor &color) { painter->save(); QRect rect = this->rect(); painter->setPen(QPen(QColor(55,143,250),2)); painter->drawRoundedRect(rect,4,4); painter->restore(); } void LunarCalendarYearItem::drawYear(QPainter *painter) { int width = this->width(); int height = this->height(); int side = qMin(width, height); painter->save(); //根据当前类型选择对应的颜色 QColor color = currentTextColor; if (dayType == DayType_MonthPre || dayType == DayType_MonthNext) { color = otherTextColor; } else if (dayType == DayType_WeekEnd) { color = weekColor; } painter->setPen(color); QFont font; font.setPixelSize(side * 0.2); //设置文字粗细 font.setBold(true); painter->setFont(font); QRect dayRect = QRect(0, 0, width, height / 1.7); QString arg = QString::number(date.year()) /*+ "年"*/; painter->drawText(dayRect, Qt::AlignHCenter | Qt::AlignBottom, arg); painter->restore(); } bool LunarCalendarYearItem::getSelect() const { return this->select; } bool LunarCalendarYearItem::getShowLunar() const { return this->showLunar; } QString LunarCalendarYearItem::getBgImage() const { return this->bgImage; } LunarCalendarYearItem::SelectType LunarCalendarYearItem::getSelectType() const { return this->selectType; } QDate LunarCalendarYearItem::getDate() const { return this->date; } QString LunarCalendarYearItem::getLunar() const { return this->lunar; } LunarCalendarYearItem::DayType LunarCalendarYearItem::getDayType() const { return this->dayType; } QColor LunarCalendarYearItem::getBorderColor() const { return this->borderColor; } QColor LunarCalendarYearItem::getWeekColor() const { return this->weekColor; } QColor LunarCalendarYearItem::getSuperColor() const { return this->superColor; } QColor LunarCalendarYearItem::getLunarColor() const { return this->lunarColor; } QColor LunarCalendarYearItem::getCurrentTextColor() const { return this->currentTextColor; } QColor LunarCalendarYearItem::getOtherTextColor() const { return this->otherTextColor; } QColor LunarCalendarYearItem::getSelectTextColor() const { return this->selectTextColor; } QColor LunarCalendarYearItem::getHoverTextColor() const { return this->hoverTextColor; } QColor LunarCalendarYearItem::getCurrentLunarColor() const { return this->currentLunarColor; } QColor LunarCalendarYearItem::getOtherLunarColor() const { return this->otherLunarColor; } QColor LunarCalendarYearItem::getSelectLunarColor() const { return this->selectLunarColor; } QColor LunarCalendarYearItem::getHoverLunarColor() const { return this->hoverLunarColor; } QColor LunarCalendarYearItem::getCurrentBgColor() const { return this->currentBgColor; } QColor LunarCalendarYearItem::getOtherBgColor() const { return this->otherBgColor; } QColor LunarCalendarYearItem::getSelectBgColor() const { return this->selectBgColor; } QColor LunarCalendarYearItem::getHoverBgColor() const { return this->hoverBgColor; } QSize LunarCalendarYearItem::sizeHint() const { return QSize(100, 100); } QSize LunarCalendarYearItem::minimumSizeHint() const { return QSize(20, 20); } void LunarCalendarYearItem::setSelect(bool select) { if (this->select != select) { this->select = select; this->update(); } } void LunarCalendarYearItem::setShowLunar(bool showLunar) { this->showLunar = showLunar; this->update(); } void LunarCalendarYearItem::setBgImage(const QString &bgImage) { if (this->bgImage != bgImage) { this->bgImage = bgImage; this->update(); } } void LunarCalendarYearItem::setSelectType(const LunarCalendarYearItem::SelectType &selectType) { if (this->selectType != selectType) { this->selectType = selectType; this->update(); } } void LunarCalendarYearItem::setDate(const QDate &date) { if (this->date != date) { this->date = date; this->update(); } } void LunarCalendarYearItem::setLunar(const QString &lunar) { if (this->lunar != lunar) { this->lunar = lunar; this->update(); } } void LunarCalendarYearItem::setDayType(const LunarCalendarYearItem::DayType &dayType) { if (this->dayType != dayType) { this->dayType = dayType; this->update(); } } void LunarCalendarYearItem::setDate(const QDate &date, const QString &lunar, const DayType &dayType) { this->date = date; this->lunar = lunar; this->dayType = dayType; this->update(); } void LunarCalendarYearItem::setBorderColor(const QColor &borderColor) { if (this->borderColor != borderColor) { this->borderColor = borderColor; this->update(); } } void LunarCalendarYearItem::setWeekColor(const QColor &weekColor) { if (this->weekColor != weekColor) { this->weekColor = weekColor; this->update(); } } void LunarCalendarYearItem::setSuperColor(const QColor &superColor) { if (this->superColor != superColor) { this->superColor = superColor; this->update(); } } void LunarCalendarYearItem::setLunarColor(const QColor &lunarColor) { if (this->lunarColor != lunarColor) { this->lunarColor = lunarColor; this->update(); } } void LunarCalendarYearItem::setCurrentTextColor(const QColor ¤tTextColor) { if (this->currentTextColor != currentTextColor) { this->currentTextColor = currentTextColor; this->update(); } } void LunarCalendarYearItem::setOtherTextColor(const QColor &otherTextColor) { if (this->otherTextColor != otherTextColor) { this->otherTextColor = otherTextColor; this->update(); } } void LunarCalendarYearItem::setSelectTextColor(const QColor &selectTextColor) { if (this->selectTextColor != selectTextColor) { this->selectTextColor = selectTextColor; this->update(); } } void LunarCalendarYearItem::setHoverTextColor(const QColor &hoverTextColor) { if (this->hoverTextColor != hoverTextColor) { this->hoverTextColor = hoverTextColor; this->update(); } } void LunarCalendarYearItem::setCurrentLunarColor(const QColor ¤tLunarColor) { if (this->currentLunarColor != currentLunarColor) { this->currentLunarColor = currentLunarColor; this->update(); } } void LunarCalendarYearItem::setOtherLunarColor(const QColor &otherLunarColor) { if (this->otherLunarColor != otherLunarColor) { this->otherLunarColor = otherLunarColor; this->update(); } } ukui-panel-3.0.6.4/plugin-calendar/lunarcalendarwidget/statelabel.cpp0000644000175000017500000000170514203402514024262 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see buttons() == Qt::LeftButton){ Q_EMIT labelclick(); } return; } ukui-panel-3.0.6.4/plugin-calendar/lunarcalendarwidget/lunarcalendaritem.h0000644000175000017500000002201214203402514025273 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #ifdef quc #if (QT_VERSION < QT_VERSION_CHECK(5,7,0)) #include #else #include #endif class QDESIGNER_WIDGET_EXPORT LunarCalendarItem : public QWidget #else class LunarCalendarItem : public QWidget #endif { Q_OBJECT Q_ENUMS(DayType) Q_ENUMS(SelectType) Q_PROPERTY(bool select READ getSelect WRITE setSelect) Q_PROPERTY(bool showLunar READ getShowLunar WRITE setShowLunar) Q_PROPERTY(QString bgImage READ getBgImage WRITE setBgImage) Q_PROPERTY(SelectType selectType READ getSelectType WRITE setSelectType) Q_PROPERTY(QDate date READ getDate WRITE setDate) Q_PROPERTY(QString lunar READ getLunar WRITE setLunar) Q_PROPERTY(DayType dayType READ getDayType WRITE setDayType) Q_PROPERTY(QColor borderColor READ getBorderColor WRITE setBorderColor) Q_PROPERTY(QColor weekColor READ getWeekColor WRITE setWeekColor) Q_PROPERTY(QColor superColor READ getSuperColor WRITE setSuperColor) Q_PROPERTY(QColor lunarColor READ getLunarColor WRITE setLunarColor) Q_PROPERTY(QColor currentTextColor READ getCurrentTextColor WRITE setCurrentTextColor) Q_PROPERTY(QColor otherTextColor READ getOtherTextColor WRITE setOtherTextColor) Q_PROPERTY(QColor selectTextColor READ getSelectTextColor WRITE setSelectTextColor) Q_PROPERTY(QColor hoverTextColor READ getHoverTextColor WRITE setHoverTextColor) Q_PROPERTY(QColor currentLunarColor READ getCurrentLunarColor WRITE setCurrentLunarColor) Q_PROPERTY(QColor otherLunarColor READ getOtherLunarColor WRITE setOtherLunarColor) Q_PROPERTY(QColor selectLunarColor READ getSelectLunarColor WRITE setSelectLunarColor) Q_PROPERTY(QColor hoverLunarColor READ getHoverLunarColor WRITE setHoverLunarColor) Q_PROPERTY(QColor currentBgColor READ getCurrentBgColor WRITE setCurrentBgColor) Q_PROPERTY(QColor otherBgColor READ getOtherBgColor WRITE setOtherBgColor) Q_PROPERTY(QColor selectBgColor READ getSelectBgColor WRITE setSelectBgColor) Q_PROPERTY(QColor hoverBgColor READ getHoverBgColor WRITE setHoverBgColor) public: enum DayType { DayType_MonthPre = 0, //上月剩余天数 DayType_MonthNext = 1, //下个月的天数 DayType_MonthCurrent = 2, //当月天数 DayType_WeekEnd = 3 //周末 }; enum SelectType { SelectType_Rect = 0, //矩形背景 SelectType_Circle = 1, //圆形背景 SelectType_Triangle = 2, //带三角标 SelectType_Image = 3 //图片背景 }; explicit LunarCalendarItem(QWidget *parent = 0); QMap> worktime; QString handleJsMap(QString year,QString month2day); //处理js解析出的数据 protected: void enterEvent(QEvent *); void leaveEvent(QEvent *); void mousePressEvent(QMouseEvent *); void mouseReleaseEvent(QMouseEvent *); void paintEvent(QPaintEvent *); void drawBg(QPainter *painter); void drawBgCurrent(QPainter *painter, const QColor &color); void drawBgHover(QPainter *painter, const QColor &color); void drawDay(QPainter *painter); void drawLunar(QPainter *painter); private: bool hover; //鼠标是否悬停 bool pressed; //鼠标是否按下 bool select; //是否选中 bool showLunar; //显示农历 QString bgImage; //背景图片 SelectType selectType; //选中模式 QDate date; //当前日期 QString lunar; //农历信息 DayType dayType; //当前日类型 QColor borderColor; //边框颜色 QColor weekColor; //周末颜色 QColor superColor; //角标颜色 QColor lunarColor; //农历节日颜色 QColor currentTextColor; //当前月文字颜色 QColor otherTextColor; //其他月文字颜色 QColor selectTextColor; //选中日期文字颜色 QColor hoverTextColor; //悬停日期文字颜色 QColor currentLunarColor; //当前月农历文字颜色 QColor otherLunarColor; //其他月农历文字颜色 QColor selectLunarColor; //选中日期农历文字颜色 QColor hoverLunarColor; //悬停日期农历文字颜色 QColor currentBgColor; //当前月背景颜色 QColor otherBgColor; //其他月背景颜色 QColor selectBgColor; //选中日期背景颜色 QColor hoverBgColor; //悬停日期背景颜色 public: // QString getHoliday(int month,int day); bool getSelect() const; bool getShowLunar() const; QString getBgImage() const; SelectType getSelectType() const; QDate getDate() const; QString getLunar() const; DayType getDayType() const; QColor getBorderColor() const; QColor getWeekColor() const; QColor getSuperColor() const; QColor getLunarColor() const; QColor getCurrentTextColor() const; QColor getOtherTextColor() const; QColor getSelectTextColor() const; QColor getHoverTextColor() const; QColor getCurrentLunarColor() const; QColor getOtherLunarColor() const; QColor getSelectLunarColor() const; QColor getHoverLunarColor() const; QColor getCurrentBgColor() const; QColor getOtherBgColor() const; QColor getSelectBgColor() const; QColor getHoverBgColor() const; QSize sizeHint() const; QSize minimumSizeHint() const; public Q_SLOTS: //设置是否选中 void setSelect(bool select); //设置是否显示农历信息 void setShowLunar(bool showLunar); //设置背景图片 void setBgImage(const QString &bgImage); //设置选中背景样式 void setSelectType(const SelectType &selectType); //设置日期 void setDate(const QDate &date); //设置农历 void setLunar(const QString &lunar); //设置类型 void setDayType(const DayType &dayType); //设置日期/农历/类型 void setDate(const QDate &date, const QString &lunar, const DayType &dayType); //设置边框颜色 void setBorderColor(const QColor &borderColor); //设置周末颜色 void setWeekColor(const QColor &weekColor); //设置角标颜色 void setSuperColor(const QColor &superColor); //设置农历节日颜色 void setLunarColor(const QColor &lunarColor); //设置当前月文字颜色 void setCurrentTextColor(const QColor ¤tTextColor); //设置其他月文字颜色 void setOtherTextColor(const QColor &otherTextColor); //设置选中日期文字颜色 void setSelectTextColor(const QColor &selectTextColor); //设置悬停日期文字颜色 void setHoverTextColor(const QColor &hoverTextColor); //设置当前月农历文字颜色 void setCurrentLunarColor(const QColor ¤tLunarColor); //设置其他月农历文字颜色 void setOtherLunarColor(const QColor &otherLunarColor); //设置选中日期农历文字颜色 void setSelectLunarColor(const QColor &selectLunarColor); //设置悬停日期农历文字颜色 void setHoverLunarColor(const QColor &hoverLunarColor); //设置当前月背景颜色 void setCurrentBgColor(const QColor ¤tBgColor); //设置其他月背景颜色 void setOtherBgColor(const QColor &otherBgColor); //设置选中日期背景颜色 void setSelectBgColor(const QColor &selectBgColor); //设置悬停日期背景颜色 void setHoverBgColor(const QColor &hoverBgColor); //五个字以上节日名称显示tooltip bool event(QEvent *event); Q_SIGNALS: void clicked(const QDate &date, const LunarCalendarItem::DayType &dayType); }; #endif // LUNARCALENDARITEM_H ukui-panel-3.0.6.4/plugin-calendar/lunarcalendarwidget/image/0000755000175000017500000000000014203402514022515 5ustar fengfengukui-panel-3.0.6.4/plugin-calendar/lunarcalendarwidget/image/bg_calendar.png0000644000175000017500000000624414203402514025452 0ustar fengfengPNG  IHDRHHUGgAMA a cHRMz%u0`:o_FbKGD pHYs  tIMEwXX][q1am JhE~3_98yppJ%H8("3?]NCw}Ꟗ֭y?e*j`@jr1Kӯ?W+RY?<0 sd۠\P@-_}k}xťE(3N Z06>(gDnN+fSR¶!erym5凯Ϳ~;R]ʸ`pOL_9?2Yn4r}nDI)pBZ +V}nbGZ *JݪrR9YLl`P[ϔgNMLWVV>^d$ /yڶh5q"< LJ'^^4\P//W~juw+=*$F*+.!#Q*/8Ƀϼ:=Jyz19IsmZ]tuDL@:T>;Rf~ة{{1XJlZӋiP!i@:T^yʎsL>Cg 3P( }z H @Kّ 8%[=Z] y8ΏA$|̂L@O˥#5g~U)5_y=m[s#b ʀ(hVŮLyFʉ7 ҀtgԞSJJМAH|xʶ+f"MSZfK9z"> 9#Dq`Ebj%K)z\LYy[~0`֣$ R̤\ (w>oEׁtp?YJ}u)3MuD5(dz$͌A]zWA VguT8[)1; Jұ%+1iN /ĐKGCC!?@@< <^.nLAdf1_Pew2%bG$w$[ Cv1ݢi(FQ,eXG) 6x~sN4ܑ{HO̐`@gM^3P JUdPib2.[hi@ڦvRFi+(?"R`^@)1Q }lrxr3(J= PfAng2s? nRO`Q(>Ȩ|F#J7&WPyZAAmp/ NIP wf!irFYU=]G]*ވA]_T+^,2'; \-KE; RP$Vlݰ =V)̞d.nzv:`oI*&EE{ p @+(ݍ$L@CylHWD 1$CtL4#YfTD* m _g cd][nsD+bӂuZhbP +-8+J}tXa*(8~(1!VTM4f &uZ{_baIxùRȂDp U D7o5DkZeZ{).r'm)+ P{i;ߔ|u?A:T@滎GG_i^aPKʟ-ub!"5[?m?] Ù*#m߽躿y "%k@2~ټZT.r|@"e=8ο4b@]dz(rͶ1csI_;"Xp ׽0/ Cfy[ʥm=m16Wb[GG{W{պ)`=dn#ẹ9߷wDD・owf gV}2KRem!, hȰYBt&7ApOp2imMR};Tu#BN^n~.>N^n~ / _!"""`%!@P`p 0@P`pd]YTC2 ߸ݺ  p%tF#fM',KLPXJvY#?+X=YKLPX}Y ԰.-, ڰ +-,KRXE#Y!-,i @PX!@Y-,+X!#!zXYKRXXY#!+XFvYXYYY-, \Z-,"PX \\Y-,$PX@\\Y-, 9/- , }+XY %I# &JPXea PX8!!Ya RX8!!YY- ,+X!!Y- , Ұ +- , /+\X G#Faj X db8!!Y!Y- , 9/ GFa# #JPX#RX@8!Y#PX@e8!YY-,+X=!! ֊KRX #I UX8!!Y!!YY-,# /+\X# XKS!YX&I## I#a8!!!!Y!!!!!Y-, ڰ+-, Ұ+-, /+\X G#Faj G#F#aj` X db8!!Y!!Y-, %Jd# PX<Y-,@@BBKcKc UX RX#b #Bb #BY @RX CcB CcB ce!Y!!Y-,Cc#Cc#-1]=/Ͱ 2/ְ Ͳ  +@ +@  + +@ +@ ++014>3!2!2#!"&463!&]$(($+@&&&&@+F#+&4&&4&x+++ͳ+)Ͳ+,/ְ$Ͱ#2$Ͱ/$!+"2ͰͰ/-+6+ #. #  " "#.... ..@(9!99!99014>32467632".4>32".Dhg-iW&@ (8DhgZghDDhg-iWDhgZghrdN+'3 8(2N++NdN+';2N++!P+Ͱ!/"/ְͰ+ ͱ#+$9  99! $9016$ #"'#"$&  oo|W%L46$܏r1ooܳ%54L&V|oMr*MI+ Ͱ"/5ͰK/N/ְͰ+2+B2 ͱO+5"9K&*$9015463!2#!"&73!265+".'&%&';2>767>5<.#!"^BB^^B@B^   %3@m00m@3% :"7..7":6] @  @B^^BB^^B  $΄+0110+$@t1%%1+;  /ְͰͱ+014632>32"'.>oP$$Po>4 #L~'T/ Ͳ  +  +2'/#(/ְͰͳ%+!Ͱ!/%ͱ)+!9%9990154>322>32#!"&6   6Fe= BSSB =eF6 yy@>ƒ5eud_C(+5++5+(C_due5xV> /?O_o /ͱSt22/|3#Ͱ2,/[333ͱc2254&'.7> $&462"&+i *bkQнQkb* j*zzLhLLhLBm +*i JyhQQhyJ i*+ mzz4LL44LL/?Ob/ ,3267676;27632#"/+"&/&'#"'&'&547>7&/.$264&" (C  ,/ 1)  $H  #H  ,/ 1)  ~'H Ԗ ..9Q $ k2 k w3 [20 6%2X  % l2 k r6 [21ԖԖ#/?GWg(+Ͱ!/.33ͱ@22E/ h/ְ$Ͳ$ +@ +$0+9Ͱ9H+QͰQX+aͰa-+Ͳ- +@ +i+0$99@9HEG99XQB9aA9-9!(43!2!2+#!"&5#"&3!2>5!46;2+"&!'&'!46;2+"&%46;2+"&5FN(@(NF5`^BB^`@@@`0 o@@@@ @%44%@LSyuS:%%@u  @@f!5=3+.36/"ְ2Ͱ2/++Ͱ2+Ͱ/7+/2'$9016762546;2#"' '&/465 #!!!"&  X  >  LL >??&&oWh J A J& &&#H/Ͱ/Ͱ/$/ְͰ+Ͱ+ ͱ%+9#901463!2#!"&7!!"&5!!&'&'8((`8(8((8`(8x @(8(`((88H8( 9  , /Ͱ*/Ͳ* +@! +/-/ְ Ͱ +&Ͳ& +@ +&+ͱ.+  $9& $9* $9 $901$  $ >. 546;46;2#!"&aa^(@a^(@`@2N1C*0+3(/5Ͱ?/D/E+(09901747>3!";26/.#!2#!26'.#!"3!";26'5.+"2$S   S$.@   @.  I6>  >6I     @  -5=u+1Ͱ82+Ͱ5/<3 Ͱ2>/ְ"Ͱ"3+7Ͱ7;+Ͳ; +@; +?+")*$93 .997&9 )*99015463!2?!2#!"&63!463!2!2"'&264&"264&"8(ч::(88(@(8E*&&*@6@L&4&&4&4&&4`@(8888((88'&&@')@*4&&4&&4&&4& 0m /Ͱ/1/ְ Ͱ +$Ͳ$ +@$( +$+ͱ2+  0$9$,-99 $9,$901$  $ >. 6;46;232"'&aa^(0  a^(^` @ 0m /Ͱ/1/ְ Ͱ ,+%Ͳ,% +@, +%+ͱ2+,  $9%99  $9($901$  $ >. 4762++"&5#"&aa^(. ?  @a^( ? `#%+Ͱ2+Ͱ /$/%+01547>3!2#!"&!!7!.'! 5@5 &&<_@_<<@>=(""=>&&   'F /Ͱ/(/ְ Ͱ +ͱ)+  $9$$901$  $ >. 476#"'&aa^( !  a^(2%J 3=0/"Ͳ"0 +"' +/4/ְͱ5+"999 99016$3276#!"'&?&#"3267672#"$&zk)'&@*hQQhwI mʬ8zoe*@&('QнQh_   z$G`/ Ͳ  +@  +2=/)Ͳ=) +@=E +52H/ְͱI+,/99  "#999=9),./999011463!23267676;2!"$'"&5!2762#!"&4?&#"+"&&&GaF * @hk4&Ak4&&@&ɆF * &&4BHrd nf&: Moe&@&&4rd/?O_oq +Ͱ-/\3$ͰT2=/l34Ͱd2M/|3DͰt2//ְͰ +0@22)ͱ8H22)+ ͱ+)PX`hpx$9015463!2#!"&73!2654&#!"546;2+"&546;2+"&546;2+"&5463!2#!"&5463!2#!"&5463!2#!"&^BB^^B@B^   @  @  @  @  @  @  @    @    @    @ @B^^BB^^B  @  @@  @  @  @  @  @  @  @  @  @  @  @ O+ͱ 22/  /ְͲ +@ ++ Ͳ  +@  +!+ 9901546;54 32#!"&!54&"8( p (88(@(8@Ԗ`@(88((88jj@7X1/Ͱ#2 ,Ͳ, +,5 +8/ְͰ ͱ9+9999$901462+"&5&476763232>32#".#"#"&@KjK@ @ @:k~&26]S &ך=}\I&5KK5H&  & x:;*4*&t,4, &KkA+3+/L/ְ.Ͱ.D+42=Ͱ=+Ͱ 2'+ ͱM+D.H9=*+$9' 9+A 990146$ #+"&546;227654$ >3546;2+"&="&/&4L4<X@@Gv"DװD"vG@@X<zz藦1!Sk @ G< _bb_ 4.54632#"&&M4&&4&""""& FUUF &&M&&M&*.D.%%G-Ikei/`/l/ְ'Ͳ' + +2'5+CͲ5C +5. +;2CT+eͲTe +TJ +]2m+`i +>G"$901463!62"'!"&%4>4.54632#"&4767>4&'&'&54632#"&47>7676'&'.'&54632#"&&M4&&4&""""& FUUF &d'8JSSJ8'& &e'.${{$.'& &&M&&M&*.D.%%'66'&;;&$ [2[ $&[4[&  #'+/37+,4333ͱ-522/3Ͱ /Ͱ /ͱ22"Ͱ/$3 Ͱ(2/03Ͱ12/*3Ͱ%28/ְ2Ͱ 2+2Ͱ2 + 2Ͱ2+$2#Ͱ(2#,+ 022/ͱ222/4+)227ͱ&229+011!!!!!!5353!353!5#!%!!535353 #'+/37;?4+@<  $(,08$3@/ְͰ+Ͱ+ Ͱ  +Ͱ+Ͱ+Ͱ+Ͱ+Ͱ +#Ͱ#$+'Ͱ'(++Ͱ+,+/Ͱ/0+3Ͱ34+7Ͱ78+;Ͱ;<+?ͱA+011373333333333333333333333333333? ?~_>_  ^?^??????_^ ?./Ͳ +@ +/ְͲ +@ ++01463!2#"'.264&"L45&%%'45%5&5KjKKj`4L5&6'45%%%%JjKKjKk5J/Ͱ2 +@ +6/ְͲ +@ +0+%ͱ7+0*-$901463!2#"'.264&"%32#"&'654'.L45&%%'45%5&5KjKKj5&%%'4$.%%5&`4L5&6'45%%%%JjKKjK5&6'45%%%54'&5 yTdty@+PͰ:/XͰa/hͰq/1Ͱ,2u/v+6=7>76&7>7>76&7>7>76&7>7>63!2#!"3!2676'#!"&'&3!26?6&#!"73!26?6&#!"  ,*$/ !'& JP$G] x6,&(sAeM `   > `   .  &k& ( "$p" . #u&#  %!' pJvwEF#9Hv@WkNC  @   @  /ְ Ͱ ͱ+01546763!2#"' #"'.'!!''!0#GG$/!' "8 8""8  X! 8'+4<o(+ Ͱ+/,Ͱ $38Ͱ+4.901546;463!232+#!"&=#"&!!!#"&=!264&"qO@8((`(@Oq 8(@(8 (8&4&&4Oq (8(`(qO` (88(8(Z4&&4&!)n/Ͱ)/%Ͱ!/ */ְͰ#+'Ͱ'+ͱ++9'# !$99%)$9 !99901546;7>3!232#!"&  462"j3e55e3jjjrgj1GG1jjrHPY'+3FͰF $A333Ͳ&=2224/KQ/R+F!?D$9'947999K9017>7;"&#"4?2>54.'%3"&#"#2327&'B03& K5!)V?@L' >R>e;&L::%P!9&WaO 'h N_":- &+# : ' 5KaQ+0Ͳ+Ͱ[/@Ͱ/63ͰJ b/ ְ`Ͱ92 ` +@  +2`S+*ͰE !ͱc+` 3699E0JNQ[$9S'9[Q *99@'9!E999017>7><5'./6$3232#"&#"32>54.#"3 4'.#"$ $5.3b[F|\8!-T>5Fu\,,jn*CRzb3:dtB2KJBx)EB_I:I^ %/2+ S:T}K4W9: #ƕdfE23j.?tTFi;J] OrB,+  )# + +)$)#+%)#+&)#+')#+()#+ #99()#9'9&9%9$9@ % #$&'()...........@ % #$&'()...........@/5799- 999017>7676'5.'732>7"#"&#&#"$ zj=N!}:0e%  y + tD3~U'#B4 # g  '2 %/!: T bRU,7a}(/%*-Y$3 Ͳ( +@({ +=D22 ( +@ m +22~/ֱM+2Ͳ2M +@2; +M2 +@MF +2e+tͱ+MD992A99e =bi$9tlmz{$9 (&9017326323!2>?23&'.'.#"&"$#"#&=>764=464.'&#"&6;#"&?62+32"/Q6 ,,$$% *'  c2N  ($"LA23Yl !x!*o!PP!~:~!PP!~:~ pP,T NE Q7^oH!+( 3  *Ueeu  wgn%%%%ao+Ͳc+z+Y/ '33/ְb2Q+*Ͳ*Q +@*8 +Q* +@QC +*+Ͱ|2+QAIYlo$9*>9@ ':prv$9 z999o99Y@ $<`fiv$901732632$?23&'.5&'&#"&"5$#"#&=>7>4&54&54>.'&#"&47>32!4&4>32#".465!#".'Q6 ,,Faw!*' =~Pl*  ($"LA23Yl  )!* @7<  <7@@7<  <7@ pP,T MF Q747ƢHoH!+( 3  tJHQ6  wh86,'$##$',686,'$##$',6/?& +Ͱ/Ͱ-/$Ͱ=/4@/A+01=463!2#!"&5463!2#!"&5463!2#!"&5463!2#!"&&&&&&&&&&&&&&&&&@&&&&&&&&&&&&&&&&/?& +Ͱ-/$Ͱ/Ͱ=/4@/A+01=463!2#!"&5463!2#!"&5463!2#!"&5463!2#!"&&&&&&&&&&&&&&&&&@&&&&&&&&&&&&&&&&/?& +Ͱ-/$Ͱ/Ͱ=/4@/A+01=463!2#!"&5463!2#!"&5463!2#!"&5463!2#!"&&&&&&&&&&&&&&&&&@&&&&&&&&&&&&&&&&/?& +Ͱ/Ͱ-/$Ͱ=/4@/A+01=463!2#!"&5463!2#!"&5463!2#!"&5463!2#!"&&&&&&&&&&&&&&&&&@&&&&&&&&&&&&&&&&/?O_oR +L3ͰD2/\3ͰT2-/l3$Ͱd2=/|34Ͱt2/ֲ 0222 Ͳ(8222+01=46;2+"&546;2+"&546;2+"&546;2+"&5463!2#!"&5463!2#!"&5463!2#!"&5463!2#!"&         @   @   @   @                  /?O6 +Ͱ=/,34ͰM/DͰ%2/P/Q+M4! 9901=463!2#!"&5463!2#!"&47632#"' 5463!2#!"&5463!2#!"&   @    @      W @   @              /?O6 +Ͱ=/34ͰM/DͰ2-/$P/Q+M49901=463!2#!"&4632#"&5463!2#!"&5463!2#!"&5463!2#!"&   @        @  @   @    @         + /!+01463!2632#"'#!"&ww '' mw@w ww**w&.i+ Ͱ./*Ͱ///ְͰ(+ 2,Ͳ,( +@,& +,+ ͱ0+,("9#9. "#%$9*$9015463!2#!"&73!2654&#!"5 462"^B@B^^BB^ @  @ppp B^^B@B^^B    @`@pppk %3+Ͱ&/ְͰͱ'+ 9 901 337'7327654#"7632@k[[  V$65&%%@`[[ &&'45%? /Ͱ//ְͰ+ͱ+ $999014 "&'&$264&",,!?H?!Ԗ,mF!&&!FԖԖ G /Ͱ//ְ Ͱ +ͱ+  99 99$901$  $3"aa^a^@-I+Ͳ +@ +./ְͰ+ͱ/+9 999 990147>7>2 %2654'.'&"QqYn 243nYqQXKjK" ]""]ً ,T5KK5$!+!77!+!*/6>H}(+Ͱ+/0Ͱ2Ͱ/I/ְͰ++2Ͱ0Ͱ2+$ͱJ+2 /457$9$-;?9990(9@ !,-.458;547632#"'&=# #"'.w M8 pB^^B@B^ww#;Noj'  'sw- 9*# @w "^BB^^B  w1T`PSA:'*4*  "g`/DY-+Ͳ- +$ +/3E/ְͰ+)ͱF+ 07A$97=A9999:9901463!2#"'&#!"3!26=4?632#!"&4?62 62"'w@?6 1 B^^B@B^ @ wwnBBnBR @w 1 ^BB^^B @ w6BnnBCv=/*3Ͱ2= +@=A +&2= +@ +2D/;ְ 2,Ͱ2,; +@,0 +2;, +@;8 + 2E+,;34$9="#$9014762!#"&4762+!5462"&=!32"'&46;!"'4&&4&&44&&4&&4f4&&44&&4&&44&&/ְͰ2+0146;2676'&'+"&&& : &&@&&Z  @  Z&&+,/ְ%Ͱ2-+0146;2676676'&''&'+"&&&  : : &&@&&Z  :  @  :  Z&&z476676'&''z::f4 :  @  : | 46&!0!`  $   /ְ Ͱ +ͱ!+01463!2#!"&%463!2#!"&&&&&&&&&@&&&&&&&& /Ͱ/ְ Ͱ ͱ+01463!2#!"&&&&&@&&&&4646&5&::` :  :4:  : +,/ְ2ͱ-+01464646;2+"&5&5&&&&&::` :  : &&&& :  : /ְ2ͱ+014646;2+"&5&&&&&:` : &&&& :  +/+017463!2#!"&&762#!&&&& 4 @@&&&&:4762 "'44444Zf647 &4?62"/Z44f444 /B /Ͱ'/0/ְ Ͱ +ͱ1+  $9'$901$  $3!;265!26=4&#!4&+"!"aa^r&&&&&&&&a^&&&&&&&& I /Ͱ//ְ Ͱ +ͱ+  $9 999901$  $3!26=4&#!"aa^r&&&&a^&&&& 7R /Ͱ2-/'38/ְ Ͱ22 +"2ͱ9+  5$9-*$901$  $32?32?654/7654/&#"'&#"aa^ZZZZa^PZZZZ #Q /Ͱ/Ͱ $/ְ Ͱ +ͱ%+  $9 99999901$  $327654/&"'&"aa^.j[4h4[a^ZiZ 6Fg /:ͰC/$Ͱ5/G/ְ7Ͱ 27 +@7 +71+ͱH+7 $91 5>$9$C9959901$  $32767632;265467>54.#";26=4&+"aa^  5!"40K(0?i+! ":oW_a^]d D4!&.uC$=1/J,XR  *:B /Ͱ/.Ͱ7/;/ְ Ͱ 2  +@ & ++2<+$901$  $%3!26=4&+4&#!";#";26=4&+"aa^2```a^R/_4-/0?333ͲGW222`/(ֲ3S222!Ͳ;K222a+01546;>7546;232++"&=.'#"&546;2>7#"&=46;.'+"&=32#&%&&%&&%&&%&S l&&l m&&m l&&l m&&@&%&&%&&%&&%&&l m&&m l&&l m&&m l&& ;F /Ͱ/. 4?'&4?62762"/"/aa^(;     a^(     ,F /Ͱ/-/ְ Ͱ +ͱ.+  %$9!)$901$  $ >. 4?6262"'aa^(f44fZ4a^(X4ff4Z&"F /Ͱ/#/ְͰ + ͱ$+  $9 "$9016$  $&&#"32>54'z8zzfY󇥔eoɒVW:zzzzO[YWo@5K / !/"+ 90147632!2#!#"'&@%&54&K&&4AA4@%&&K%54'u%@4'&&J&j&K55K$l$L%%%5K /!/"+9015463!&4?632#"/&47!"&A4&&K&45&%%u'43'K&&%@4A5K&$l$K&&u#76%u%%K&j&%K5K@!"/ְͱ#+90147632#"'+"&5"/&5&#76%%%K&56$K55K$l$K&55&%%u'43'K&&%@4AA4&&K&5K"#/ְͱ$+9014?63246;2632#"'&5&J'45%&L44L&%54'K%%u'45%u&5&K%%4LL4@&%%K'45%t%%$,O/Ͳ +% +@ + +@ +-/)ְ"Ͱ"Ͱ/.+")%9 990147!3462"&5#"#"'.'5&44&bqb>#  dž&4& 6Uue7D#  "/46262#!"&47'&463!2"/"/&4L  r &@& L&&&4  r@&L r  4&&m L4&&@& r s/647'&463!2"/"/46262#!"& L&&&4  r&4L  r &@& L4&&@& r&L r  4&&#J+!/3Ͱ2! +@ +$/ְ2Ͱ 2 +@ + +@ +%+015463!46;2!2#!+"&5!"&8(8((8(88(`8((8`(8`(8(88(`8((8`(88(8 /Ͱ/+015463!2#!"&8((88(@(8`(88((88z56//ְ 2(Ͱ27+0167-.?>46;2%6 '%+"&5&/m. .@g. L44L .g@. .@g.L44L.g@egg.n.34LL4͙.n.gg.n.4LL43.n -0 /!Ͱ*/Ͱ/.//+*999901$  $;2674'&+";26=4&+"aa^    a^  m /  @*3AJ#+7Ͱ(/3Ͱ2/>3.ͰB22/H3 Ͱ2K/&ְ4ͳ4&+,Ͳ, +@ +4;+ͳ;+FͰF/ͲF +@ +L+;, /B$9F&992. $901463!"&46327632#!2+#!"&5#"&;'&#";26=5!3264&#"]]k==k]]`8((8`x8(~+($$(88(+ @MM`(88(vP88,8P89Oh1+J/P/ ְ:Ͳ : +@ +:Ͱ/:H+ ͱQ+:,/99H'99 9J1 ',=$9 990154>54&'&54>7>7>32#"'.#"#".'.327>76$3264&#">J> Wm7' '"''? ./+>*&^&&zy#M6:D 35sҟw$ '% ' \t&_bml/J@L@ N&^|h&4&c3.+ /4/5+01463!2#!"&54>54'''. @  1O``O1BZZ71O``O1CZZ7  @  `N]SHH[3^)TtbN]SHH[3`)Tt!1H +Ͱ/%Ͱ//2/ְ"ͱ3+" 9% $9/ $901476  '7 $7&' 547265463264&#"ٌ''l==8(zV}D##D#EuhyyhulVz(#-=OUq>+?Ͳ+;/Ͳ; +@ +V/*ְ2.Ͳ.* +@. +W+.* &,999?> 99;@ &0,EJPQ$999901476!27632#"'&547.'77.547265463264&#"76$7&'7 Y[6 $!i\j1  z,XlNWb=8(zV}0Jiys?_9'Fu>La   YF  KA؉Eu?kyhulVz(Äsp@_"F"@Q-'#3 /'Ͱ0/Ͱ /4/5+017>2#!"&'&;2674'&+";26=4&+"#"'&' +&/& `  L4,@L 5 `   a 5 L@,4LH` `  #'+/?CGKOSWgkos!/$Ͳ@Lh222'/BNj333(ͲDPl222+/FRn333,ͲHTp222//JVr333ͱ223Ͱ[2Ͱ2J> +@J" +>J +@> +r/s+7M^_999J /CO$9>A99901=46;2>767>3!54632#"&=!"+"&546;2.+"&673!54632#"&=".0N<* .)C=W]xD ?  0N<* .)C=W]xDmBZxPV3!   mBZxPV3!\-7H)O]-7H)   ".=&' +'/ְ Ͱ ͱ(+ $99014>$32#"'&'5&6&>7>7&LdFK1A  0) e٫C58.H(Y#3CR!/Ͳ! +@ +21/@3(Ͱ82D/ְ$2 Ͱ,2 +42Ͱ<2E+  !99015463!22>=463!2 $463!2#!"&%463!2#!"&&&/7#"462"$462"& & &&&%ZKjKKj5KjKKj4& %&%z 0&4&&3D7KjKKjKKjKKjK+/+015463!2!2#!"&\@\\\@\\\ \@\W*-(+Ͱ/ Ͳ  +@  ++/,+(9015463!2!2!"4&47>3!2#!"&\@\ \^=IP+B@"5+B"5\\ \_Ht#3G#t3G@; /ְͲ +@ +2 +@ +2!+ $901646;#"&4762+32"'@&&4&&4&4&&44&&4@;/Ͳ +@ +2 +@ + 2 /!+$9014762!5462"&=!"'4&&44&&4f4&&4&&#'+/v+ Ͱ /$(,333!Ͳ! +@!% +@!) +@!- +/0/ְͰ +#Ͱ#$+'Ͱ'(++Ͱ+,+/Ͱ/+ ͱ1+015463!2#!"&73!2654&#!"!3!3!3!^B@B^^BB^ @   B^^B@B^^B    @[ /Ͱ$/Ͳ$ +@$? +A/ְ3Ͱ.23+ͱB+39"0=?$9 99$9015463!2#!"&%32>54'6767&#".'&'#"'#"www@wpČe1?*8ADAE=\W{O[/5dI kDtww@w^GwT -@ (M& B{Wta28r=Ku?RZ$X!/ 3Ͱ2/3Ͱ/%/ְ!Ͱ2! +2 Ͱ Ͱ/&+!9 99015463!2+37#546375&#"#3!"&www8D`Twww@w`6: &.>+ Ͱ/"Ͱ./2ͰaԖ68(B^5KK55KK5v@>ԖԖ(8^H1G^//5Ͳ/5 +@/* +@/H/ְ3Ͱ3>+ͱI+>3-/999 95/ -$9@ $9014$327.54632#".'#"'#"&2654'3264&"&#"2̓c`." b PTY9b '"+`N*(app)*Pppp)*P2ͣ`+"' b MRZBb ".`(*NppP*)pppP*)ck546?67&'&547>3267676;27632#"/+"&/&'#"'&547>7&/.$264&"54767&547>32626?2#"&'"'#"'&547&'&54767&547>32626?2#"&'"'#"'&547&'&2654&"2654&" "8x s"+  ")v  <  "8w s%(  ")v  > Ԗj 3>8L3)x3 3zLLz3 3>8L3)x3 3zLLz3 KjKLhLKjKLhL% #)0C vZl. Y L0" #)0C wZ l/ Y N,&ԖԖq$ ]G)FqqG^^Gqq$ ]G)FqqG^^GqV5KK54LL5KK54LL%OoN+&Ͳ:+ /P/ְͰ.+3ͱQ+&(L999.069939CD999&N69L$9 99 .03$90146$ #"'#"&'&4>7>7.32$7>54''&'&'# E~EVZ|$2 $ |h:(t}| $ 2$|ZV쉉X(  &%(HZT\MKG{xH(%& (X08m/C+(Ͳ-+9Ͱ32m/ͰW/Ͱ^/n/ְ2Ͱ26+9Ͱ9[+Ͳ[ +@[X +F+#ͰK Q3!ͰN Ͱ#T+ͱo+6=_+   a_  +a`a_+ #9`a_9 _`a...... _`a......@62.9[9+-A$99#FL9N9m9#7FT$99f9^[c$9015463!6767>763232+"&'&#!"&6264&"32;254'>4'654&'>54&#!4654&#+K5$e:1&+'3TF0h1 &<$]`{t5K&4&&4 %/0Ӄy#5 +N2`@`%)7&,$)' 5KK5y*%Au]cgYJ!$MCeM-+(K4&&4&IIJ 2E=\#3M:;b^v+D2 5#$2:p0$/JͰ/QͰ//;Ͱp/93Ͱf/ q/ְ4Ͱ48+pͰpM+ͲM +@MP +^+W2Ͱb Ͱ^Z ͳT^+ͱr+6?m+ *(GI*)*(+GHGI+HGI #9)*(9()*GHI......()*GHI......@849Mp$/h$99b\9Z9J-FM$9Q.C99;T99p5b$901463!27>;2+#"'.'&'&'!"&264&"322654&5!2654&'>54'64&'654&+"+K5 tip<& 1h0##T3'"( 0;e$5K&4&&4 ')$,&7)%`@``2N+ 5#bW0/% 5K(,,MeCM$!JYgc]vDEA%!bSV2MK4&&4&$#5 2D+v^b;:M3#\=E2 JIURI@47%63#"&547&8?Vy% I) b955/(3Ͱ 2:/ְͰ#+ͱ;+# $9014632>32"'.7 654.""'.">oP$$Po>4 #LHexh\`C++I@$$@I+Z$_dC/Q|I.3MCCM3.I| (@F&+Ͱ>/-Ͳ>- +@>: +-> +@-2 +/A/ְͱB+->569901463!2#!"3!:#!"&463!462"&5!"&w@  B^^B   w&&4 4&@& w   ^B@B^   & &4& &5 /ͱ *22 +@' +//Ͱ 33Ͱ6/ְͰͰ+ Ͱ !+*Ͱ*++ ͱ7+99 99!1299*/39919015463!2#!"&;265."3#347>3234&#"35#www@wG9;HFtIf<,txIww@w3EE34DD@J&#1ueB".~ /3ͱ%22  +@  +/+33 //ְͰͳ+#Ͳ# +@ ++(Ͱ(/Ͳ( +@ +(+ͱ0+(#9901463"&463!2#2#!+"'!"&2654&"c4LL44LL4c&S3 Ll&@{LhLLhL{& &z'?a%+Ͳ% +@ + /@/ְͲ +@ ++!ͱA+()-.<$9!+9 +7:<$901463!2#!"3!26546;2#!"&47'&463!2"/"/w@B^^B@B^@ww &&&4t  r @w@^BB^^B@w 4&&&t r@F<+Ͱ/Ͳ +@ + +@ +%/3A/ ְ8ͱB+ 9901463!462"&5!"&>3!2654&#!*.54&>3!2#!"&54&&4 4&@&~ @B^^B  @ww & &4& & ^BB^   w@w ;BI(//Ͱ 2B/G3Ͱ2B +@ +J/ְ<Ͱ<2+Ͳ2 +@ +#H222 +@2 ++A22F+ͱK+2<7?99FC99B/8?C$9015463!5463!2!232#!"&=4632654&'&'.7&5!>=!8( ^B@B^ (8Sq*5&=CKuuKC=&5*q͍SJ6(8`B^^B`8(GtO6)"M36J[E@@E[J63M")6OtGNN`YaipxW/ 3MͰ/3{ͱ22`/\Ͱ%//ְ.Ͱ.^ ZͰZ/^Ͱ.+ͱ+ZAF99^@+,454'6'&&"."&'./"?+"&6'&6'&&766'&6'7436#6&76www 49[aA)O%-j'&]]5r,%O)@a[9( 0BA; + >HCw  $  /    61=ww@wa-6OUyU[q ( - q[UyUP6$C +) (  8&/ &  A   )    /7?p3+:3ͰͰ7/>3 Ͱ2@/,ְ%Ͱ%5+9Ͱ9=+Ͳ= +@= +A+%,995 0999 9 ()9901463!3!267!2#!"&&762#!#!"&5!"264&"264&"8(c==c(88(@(8E6*&&**&4&&4&4&&4 @(88HH88((88'@'(@&&4&&4&&4&&4&2d*/$3;ͰA2;> 'Ͱ[/ ͰX U3 Ͱ2e/0ְ6Ͱ- 39Ͱ326G+ͰN Q3ͱ22f+6^+ LJ+Â+ +LKLJ+ #9KLJ9JKL.......JKL......@N6 *$;AS[$9X>-39GQ$9 S9014>76763232632#"&#"#"&54654&732632327>54&'.54654'&#"#"&#"$IVNz<:LQJ  |98aIea99gw   N<;+gC8A`1oζA;=N0 eTZ  (:7,oIX(*()W,$-,-[% 061IO4767>3232>32#".'&'&'&'.382W# & 9C9 Lĉ" 82<*9FF e^\3@P bMO0# -\^e FF9*<28 "L 9C9 & #W283 #0OMb P@3* +Ͱ/ /ְͰ+ ͱ!+01463!2#!"&73!2654&#!"w@www^B@B^^BB^ @wwwwB^^B@B^^B#D#/Ͳ# +@# +2$/ְͰ!+ ͱ%+9!9 901546763!2#"' #"'.77!'!!''!0#GG$/!'YY "8 8""8  X! 8AUUjUN /!ͰQ/ͲQ +@Q4 +V/ְͰ&+ Ͳ& +@&A +W+&F9Q!09015463!2#!"&3267654'./.#"#".'.'.54>54.'.#"www@w <90)$9G55 :8 c7 )1)  05.Dww@w`$)0< D.50 + AB 7c  )$+ -.1 ,T17327.'327.=.547&546326767# ,#+i!+*pDNBN,y[`m`%i]]C_LҬ}a u&,SXK &$f9s? (bEm_@/3Ͱ2 +@ + //ְ2Ͱ 2 +@ ++01!54632#"!#!_ЭQV<%'w(ں HH RH /S/ְ)Ͱ)+ͱT+)54'6'&&"."&'./"?'&aa49[aA)O%-j'&]]5r,%O)@a[9( 0BA; + >HCaoMa-6OUyU[q ( - q[UyUP6$C +) (  8&/ &fM%f#+Ͱ2/ Ͳ +@ +&/ְͲ +@ + +@ ++ ͱ'+ 99#99015463!54 +"&54&"32#!"&8(r&@&Ԗ`(88(@(8`@(8&&jj8((88#'+V+ Ͱ$/(3%Ͱ)2/Ͱ /,/ְͰ2$+'Ͱ'+2 ͱ-+'(*99015463!2#!"&73!265!!54&#!"5!35!^B@B^^BB^ @   B^^B@B^^B  `  !=Y+233Ͳ +@ +;/'>/ֱ"22ͱ?+;99799;:999')901<62"5476;+"&'&'.5476; +"&'&$'.pppp$qr $!ߺ % }#pppp rqܠ!E$ ֻ!# %%/7?+Ͱ7/>33Ͱ:2"/&Ͱ'2,/@/ְͰ1+5Ͱ59+=Ͱ=+ͱA+6<7+ &./#7+ '.(   (/...... &'(/........@01547>3!2#!"&73!2654&#!"7!.#!"462"6462"\77\^B@B^   @ 2!/B//B/B//B@2^5BB52B^^B  @    B//B//B//B/.4B5/)ְͲ) +@) +1+Ͱ 2ͱ6+)$91 /$9015463! 22##%&'.67#"&%^B4L5KK5L4_u:B&1/&.- zB^yvB^L4KjK4L[!^k'!A3;):2*767>32!2+#"'&#!"&6264&"323254'>4'654&'!2654&#!4>54&#"+K5 A# ("/?&}vhi!<;5K&4&&4 HQ#5K4LN2$YGB (HGEG 5K J7R>@#zD9eME;K4&&4&@@IJ 2E=L43M95S+C=,@QQ93ksF+&Ͳ"+JͰn21/7ͰM/Ͱi/Ͱ`/ t/ְ4Ͱ4)+CͰ, ?Ͱ82C)+cͲc +@ch +CK+mͰmq+ͱu+,4/099?;9C)=99Kc" &F$9qm!991J*=Cr$97;9M499RWf999`Zc$901463!&546323!2#!"#"&?&547&'#"&73!32>;#".'.'&'&'.#"!"264&"hv}&?/"( #A  5KK5;=!iL4K5#aWTƾH #A<(H(GY$2N&4&&4gR7J K55K;ELf9>h4L=E2 JI UR@@2*!Q@.'!&=C+S59M4&&4&2`hh+?Ͱ/dͰ^/Ͳ^ +@^Y +K/Q3ͰF ͰU/ i/ְ3Ͱ3+YͰY# +>Ͱ>Q+ Ͱ ?+e2ͰD +ͱj+3/6\$9>Y U99 QN9?FLa$9hd"99^?#D$99FLN99U 9901463246326326#!"&54.'&'.7!54>54#"."&#"4&#"".#"264&"zD9eME;K55K J7R>@#,@QQ9@@IJ 2E=L43M95S+C=&4&&4}vhi!<;5KK5 A# ("/?&B (HGEG HQ#5K4LN2$Y4&&4&3hp+/@Ͱ#/JͰD2 NͰ1/7Ͳ71 +@7< +V/lͰp/q/ְ4Ͱ4.+=Ͱ= +XͰXC+(Ͱ(U+m2ͰQ +ͱr+.417c$9=:9X+@99(CF9U!HNi$9#@'9JF9N /H99V7Q$9pl99014>767>5463!2/#"'#"&5#"&732>3326532726732654.=!264&"#@>R7J K55K;ELf6Aig6Jy=C+S59M34L.9E2 JI UR@@2*! Q@.'!&&4&&4&?/"( #A  5KK5;=ihv}GY$2NL4K#5#aWTƾH #A<(H(4&&4& +B /Ͱ(/,/ְ Ͱ +ͱ-+  $9($901$  $2?64/!26=4&#!764/&"aa^-[j6[&& [6[a^M6[[6&&4[[ +B /Ͱ!/,/ְ Ͱ +ͱ-+  $9!$901$  $3!27764/&"!"aa^2&[6j[[6[ &a^&4[j[6[j[6& +B /Ͱ(/,/ְ Ͱ #+ͱ-+#  $9($901$  $2?;2652?64''&"aa^.[6&&4[[6[a^N6[ &&[6j[[ +B /Ͱ"/,/ְ Ͱ +ͱ-+  $9"$901$  $2?64/&"4&+"'&"aa^.j[6[j[6&&4[a^L6[[j6[&& [ $  $76.7"7"#76'&'.'2#22676767765'4.6326&'.'&'"'>7>&&'.54>'>7>67&'&#674&7767>&/45'.67>76'27".#6'>776'>7647>?6#76'6&'676'&2>767676&67>?&'4&'.'.'."#&6'&6&'3.'.&'&'&&'&6'&>567>#7>7636''&'&&'.'"6&'6'..'/"&'&76.'7>767&.'"67.'&'6.'.#&'.&6'&.5aa^ +  !       $     "  +       &"      4   $!   #          .0"2Α      a^   ' -( # * $  "  !     * !   (                                 P $      2 ~ /P+ Ͳ+0/ְͰ+!Ͳ! +!) +! +1+ 999!901347#"/&6264&"32>32#"&'bV%54'j&&4&&4:,{ /덹5&b'V%%l$4&&4&r! " k[G'C/37;R +4Ͱ7/Ͱ/0Ͱ3/Ͱ,/8Ͱ;/%990132327#"&462"4>322>32#!"&6  462"654'32>32+&|Kx;CBQgRpԖ 6Fe= BPPB =eF6 yy@>ߖԖgQBC;xK|pRga*+%u{QEԖԖ5eud_C(+5++5+(C_due5xV>ԖԖu%+*NQ{p%Gi/MͰW/Ͱ+ "ͰC/j/ְ&Ͱ&>+ Ͱ HͰ R+ͱk+& " h99RM999"MRY$9+ 99W -99C &$9014?632632#"/&547'#"/7327.54632654/&#"32?654/&#"#".'USxySSXXVzxTTUSxySSXXVzxTl)* 8( !(')((* 8( !SSUSx{VXXTTSSUSx{VXXT( (8 *(('(  (8 7+Ͳ+Ͳ+ /ְͰͱ+  9901467&5432632#!"t,Ԟ;F`j)6,>jK?чs !M/Ͱ/33 "/ְͲ +@ ++Ͳ +@ +#+9901&7#"&463!2+#!!'5#E8@&&&&@8EjY&4&&4&qY%q%FTbp~6+C KͰR/Ͱ/Ͱr2/YͰ`//ְͰ2+kl99R6<9999cjkl$9 .p$9Y #ow$9` mn999017>76326?'&'#"'.'&67632632 #"'#"'&6327>'&#"3276&'&#"7''54?'462"7bRSD zz DSRb)+USbn  NnbSVZ2.'Jd\Q2.'Jd\2Q\dJ'.2Q\dJ' ``!O&4&&4TFL5T II T5L;l'OT4M01B@#$rr$#@B10M5TNTЄ*$;3*$;3;$*3;$` @@Qq: $/4&&4&y@-09</1Ͱ/ Ͱ9/:Ͱ-/.Ͱ4/Ͱ(/=/ְ Ͱ /+)Ͱ) +!21Ͱ1&+ Ͱ ; +5Ͱ52+ͱ>+/ .9&1:9.-&<99 9(09015467>3!263!2#!"&5!"&7!467!#!7!!!#!7!(`((8D<(88(@(8(8(<8(`U+8(`U+(`(8((8(@(88( 8H(`<`(8+U`(8+||?w;/Ͱ /3Ͱ/@/ְͰ0+#Ͳ#0 +@#( +#+8ͱA+#099+3;$9  +08$93999014632#"'&#"32654'&#"#"'&54632#"'&ܟs] = OfjL?R@T?"& > f?rRX=Edudqq = _MjiL?T@R?E& f > =XRr?buds15Ed+233Ͱ5/Ͱ+/9Ͱ1/'A33F/ְͰ/+26Ͱ2Ͱ6=+(Ͱ(3+Ͱ+ ͱG+01463!2#!"&73463!234&'.##!"&5#!!;2654&+"8((`(8((88(@(8 08((8   @(8(`(`(88H(88(`1  `(88(  @  5463!2#!"&www@www@w/ +Ͱ/Ͱ-/$0/1+01=463!2#!"&5463!2#!"&5463!2#!"&&&&&&&&&&&&&@&&&&&&&&&&&&@'7Gl%+Ͱ Ͱ5/,Ͱ  ͰE/<Ͱ H/ֱ22ͱ 22I+%$9,5 $9E9901<62"462"462"5463!2#!"&5463!2#!"&5463!2#!"&ppppppppppp   @    @    @ 0ppppppppppp`      <L\l|Z+QͰ22Q1Ͱ/Ͳ%+7+;/!Ͱ/ͰͰj/aͰ /Ͱz/B3qͰDͰ@2Dz +@D> +}/ֱ 22ͳ0+1Ͱ1/=30ͰE+@Ͱ52E@ +@EC +@E++3Ͱ328 $Ͱ$/8ͱA228Ͱ/~+01 'L$9E&J99@ !);>$9Z!899Q'599/+4999aj $9  9014>54&#"'>32353!&732654'>75"##5!#"733!5346=#5463!2#!"&5463!2#!"&5463!2#!"&/BB/.#U_:IdDREi919+i1$AjM_39K!.EO\$9R1P$9 E;OR999%1$99015463!2#!"&476!2/&'&#"!&'&&?5732767654'&'!#"/&'&=4@2uBo  T25XzrDCBBEh:%0f#-+>;I@KM-/Q"g)0%HPIP{rQ9 @@ $&P{<8[;:XICC>.#-a)&%,"J&9%$<=DTI*'5oe71#.0(  ls +Ͱd/0ͰO/C33KͲF222t/mְ%Ͳ%m +@% +m% +@ms +%:+;2ZͲZ: +@ZM +u+6/'+ ;.?XV??;+VWVX+WVX #9>?;9<9=9>?X;<=VW........>?X<=VW.......@%m99:EFd$9ZRU99O0EPls$9KIJ999013!26=4&#!"6323276727#"327676767654./&'&'737#"'&'&'&54'&'&'@ <4"VRt8<@< -#=XYhW8+0$"+dTLx-'I&JKkmuw<=z% @@@ v '|N;!/!$8:IObV;C#V  &   ( mL.A:9 !./KLwPM$ /?O_o +ͱCs22/K{33#ͱS22,/[333ͱc22?>;5463!2&#"&5!"&5#".!#"264&"264&"@&  ?&&! 'ԖԖ@' ! LhLLh4LhLLh&@6/" && jjjj  hLLhLLhLLhLJ /Ͱ@/0Ͱ/K/ְ!Ͱ!-+CͰC=+3Ͱ3+ͱL+C-(*GH$9= 08 E$936999  H99@@ !%-36E$9014$ #"'676732>54.#"7>76'&54632#"&7>54&#"&aaok; -j=yhwi[+PM 3ѩk=J%62>Vca^ ]G"'9r~:`}Ch 0=Z٤W=#uY2BrUI1^Fk[|Lx /I3ͰA/1Ͱ/M/ְ"Ͱ".+DͰD>+4Ͱ4+ͱN+D.(+ HI$9>19F$94799A"&.47F$9015463!2#!67673254.#"67676'&54632#"&7>54&#"#"&www+U ,iXբW<"uW1AqSH1bd=Uco /ͰQ/CͰ`/YͰ)2,/p/ְ0ͰͰ0V+]Ͱ> NͰ]g+k2 ͱq+N># 3)9$9]V!CHQ$9g&+d$9CQ99`@ !5:3dfhi$9Y#0&jlno$9015463!2#!"&32>54.4>54&'37!"3274>32#".4632#".33535#5##www@w%3!##"&'&732>54.'&#"3267654.#"53533##5 YJ .H?MpJL1EF1@[Z@0HꟄ9%Fq}A:k[7'9C 5hoS6j+=Y4&P5"?j@*Q/iiQ.R*@)$1R6B@X?ZHsG;@"$ECPNZSzsS`0$/. 0$8].ggR4!9f:}R'!;ll/<W +Ͱ-/7ͱ22+ (08$9<7 !()$9015463!2#!"&2!463"&5!#4>2".673#!5##&&&&jjjj*M~~M**M~~MPM* r@&&&&Zjjjj|NN||NN|mP%``@  //+01463!2"'&&@4@&4&&4@@  //+014762#!"4&&4@4&@ /+ͱ+014762"'@4&&4@f4&&@ / +ͱ+015462"&&4@4&&@4@&:+3 Ͱ/3/ְͰ+Ͱ+ ͱ+015463!2#!"&73!!!265!^B@B^^BB^ ``  B^^B@B^^B  `@ 463!2"'4762#!"&&@4@4&4&&4@4@4&  //+01463!2"'&&@4@4&&4@@  //+014762#!"4&&4@4&:/ ;/<+015;2>76%67#!"&463!2+".'&$'.,9j9Gv33vG9H9+^B@B^SMA_bI\ A+=66=+A [">n 1&c*/11/*{'0B^^lNh^BO3@/$$/@*l +r%/Ͳ% +@%! + 22 /,/ ְͰ Ͱ++Ͱ2+!+ ͱ-+ 99+9!9% $901462+"&!3/!#>32!4&#"gdgTRdJI*Gg?QV?U JaaJIbb8!00 08iwE334>/ Ͳ  +  +)/ 5/%ְͱ6+)  12$9 99014766$32#"$'&6?6332>4.#"#!"&('kzz䜬m IwhQQhbF*@&@*eozz   _hQнQGB'(&(q4>7632&4762.547>32#".'632#"'&547"'#"'&(  &  \(  (  &  ~+54'k%%k'45%&+~(  (h  (\  &  h(  (~+%'45%l%%l$65+~  &  !3;CK]/ͰF2;/L/ְͰI+ ͱM+I@ #,48<@D$9%9;@  *.26>BJ$90146$ #!"'&264&"264&"676&'6.264&"264&"264&"LlL##KjKKjuKjKKj;P,2e2.e<^*KjKKjuKjKKjuKjKKjL;jKKjKujKKjK1M(PM+&97 #$9:3#*0$9014$ #"'#"&'5&6&>7>7&76?32$6&$ dFK1A  0) W.{+9E=ch'٫C58.H(YpJ2`[Q?l&싋%:dc+;ͲO+ /1Ͱ8/e/ְ&Ͱ&5+ͰC+Hͱf+&995 #;=a$9CEK99HNXY999;cKNa$9 991 #+$98*.CEH$90146$ #"'#"&'&4>7>7.76?32$64&$ 32$7>54''&'&'# E~EVZ|$2 $ |j`a#",5NK :(t}| $ 2$|ZV쉉X(  &%(HwR88T h̲hhZT\MKG{xH(%& (X|!>3!2%632#"'.7#"'&H  j '9 1b{(e US/*>33ʹ"26FJ$2I/43 Ͱ2 /3V/ְOͳJO+Ͱ/JͰOB+2;Ͱ26;B+GͰG/ 36Ͱ2;.+'ͳ"'.+3Ͱ3/"ͱW+0146;5463!5#"&5463!2+!232#!"&546;5!32#!"&546;5!32#!"&8(`L4`(88(@(88(`4L`(88((88(``(88((88(``(88((8 @(84L8(@(88((8L48((88(@(88((88(@(88((88;OY|D+NͲDN +D? +DI +4/$33Ͳ4 +4 +92@4 +,2P/TZ/<ְAͰAF+P2KͰV2[+A<09F%,MN$9K901476$32#"'.#"#"'.'."#"'.'.#"#"&46226562"&5462&"-U ! 1X:Dx+  +ww+  +xD:X1 &4&NdN!>!И&4&*,P  ..J< $$ 2#"&'"&547&547&547.'&7367>7654."$4632"&54&#"YYg-;</- ?.P^P.? -/<;-gD ) ) DEooE` 2cKl4 cqAAqcq1Ls26%%4.2,44,2.4%%62sL1qeO , , OeH|O--O|+ L4  .24V/ Ͳ +@ +  +@  +2/Ͳ2 +@2- +2 +@$ +5/6+ 92()990147632!2#!#"'&5463!54632#"&=!"& @  `    ` ?    @     @ -    5p+!Ͳ! +@! +./6/ְ1Ͱ Ͱ1%+Ͱ* ͱ7+19* !99 99.!$9 901467&5432632#!"27654&+4&+"#"v,Ԝ;G_j) `  _   7 ,>jL>цY _ `  5+Ͱ)2+$Ͳ+ Ͱ2/6/ְͲ +@ +-+Ͳ- +@ +7+- 99 99$992$9  901467&5432632#!";;26532654'&"v,Ԝ;G_j)    7 ,>jL>ц  `  ` PX`+%533NͰX/TͰ`/\a/ְ Ͱ R+VͰV*+1Ͱ1^ ZͰZ/^Ͱ^3 (Ͱ(/3Ͱ18+Jͱb+R 99V $9^Z#.TW$91*>AD$93(-98@9X#(38$9T!*1:J $9`@  .>@-$9\D$90154>72654&'547 7"2654'54622654'54&'46.'#!"&$462"6  %:hD:FppG9Fj 8P8 LhL 8P8 E; Dh:% yy&4&&4>ƒD~s[4Dd=PppP=d>hh>@jY*(88(*Y4LL4Y*(88(*YDw" A4*[s~Dy4&&4&>EM.+@ͰC/*3ͰM/7Ͱ/3 Ͱ2N/ְͰ ͰB++Ͱ++'Ͳ' + +'4+GͰG0 +=Ͱ=K +9ͱO+  99+-@9994'.?99G69M14932#"' 65#"&4632632 65.5462 $=.$264&"& <#5KK5!!5KK5#< &ܤ9GppG9&4&&4&$KjKnjjKjK$&jjb>PppP>buោ4&&4& %W/ 33ͳ $2/&/ְͰ +ͳ  +ͳ +Ͱ/Ͱ+"ͱ'+01546;#"&35463!23!5!32#\@@\8(@(8`@\\`@\(88(\\!-j/%./ְ"Ͳ" +@ +"'+Ͳ' +@ + '+Ͱ/ ͱ/+"+99' %($9  9990156467&5462#!"&5!"&324#"&54"8P8¾L4@Ԗ@4LgI;U (88(¥'4LjjLLIg U;@"?/Ͱ/ ͳ +Ͱ "#/ְͱ$+9"99015!#!"&463!2+#!"&3264&+jj&@\@\@PppP@j& \Ͱ>/D+01462265462265462+"&5.463!2+"&5#"&&4&&4&&4&&4&&4&G9L44L9G&L44L @&&`&&&&`&&&&=d4LL4 d &4LL4,<LSq/Ͱ*/!Ͱ:/1ͰJ/AͰ/MͰ/T/ְͰ+MͰM+ ͱU+-.=>$9M%&56EFN$9MS901463!2#!"&7!!"&5!5463!2#!"&5463!2#!"&5463!2#!"&!&'&'8((`8(8((8`(8@@@x @(8(`((88H8( @@@@@@n 9 -=M]m} -=463!2#!"&7!5463!2!!546;2+"&546;2+"&546;2+"&546;2+"&546;2+"&546;2+"&546;2+"&546;2+"&546;2+"&546;2+"&546;2+"&546;2+"&546;2+"&546;2+"&546;2+"&546;2+"&546;2+"&546;2+"&&&&& @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @ &&&&Z   @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  1AQaq463!463!2!2#!"&7!5463!2!!#!"&=!546;2+"&546;2+"&546;2+"&546;2+"&546;2+"&;26=3;2654&+"#54&+"546;2+"&546;2+"&546;2+"&546;2+"&546;2+"&&@8((8@&&& @ 8(@(8 @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @  @ & (88(&&&Z   (88( @  @  @  @  @  @ @  @  @  @   ``  @  ``  @@  @  @  @  @  @  @  @  @  @ @&/7[c3+^3"Ͱ2%/33Ͱ7/b3(Ͱ*/ ͰX/M3ͰSd/ְ'Ͳ' +@ +'$ +1Ͱ1(+ 422=ͰV2Ͱ8Ͱ= +]Ͱ]D+N2ͳaD+ͰIͰI/e+(1!"*999D]^c999a9%314]`$905\a$9(@A99*;;463!2+"&5!"&5#"!#264&";;26=326=4&+54&+"#"264&"@&@&&&ԖԖKjKKjKjKKj4&@@&&&jjjj jKKjK jKKjK ;?I /@33Ͱ%2 Ͱ3/<ͳ A$2?/J/ְͰ +Ͱ62ͳ< + Ͱ /<Ͱ$+.2ͳ=$+Ͱ)Ͱ)/@+FͱK+01546;#"&35463!23;;26=326=4&+54&+"#"!5!32#\ \`8(@(8` \\`@\(88(  \\:f.+/Ͱ%2!/Ͱ2  ͳ!+Ͱ /3;/<+2/#367$9 99!89999 901575#5#5733#5;2+31 #32+53##'53535 `@@`&&E%@`@E&&`@@`    @ :# @ @   @B + /Ͱ/Ͳ +@ +/ְͱ+ 9999017!7!!57#"&5;!@   @K5 @5K3G /ͰͰ2+/Ͱ0Ͱ%24/ְͰ++2Ͱ)2!+ ͱ5+015463!2#!"&%;265!;2654&+"!4&+"www@w&&&&&&&&ww@w&&@&&&&@&&3I /Ͱ2Ͱ0/%3Ͱ+4/ְͰ.2Ͱ+&2 Ͱ !Ͱ!/5+015463!2#!"&3!;265!26=4&#!4&+"!"www@w&@&&@&&&&&ww@w&&&@&&@&&&-M3)4762 "'$4762 "'-   2 w 2  .v   2 w 2  .3  2  ww  2    2  ww  2  M3)647 &4?62"/$47 &4?62"/ w 2   .  2v w 2   .  2   2 .  . 2    2 .  . 2M3S)64762"' "/4762"' "/M    2  ww  2    2  ww  2  .  2 w 2  .  2 w 2M3s)4?62 62"'4?62 62"'M 2    2 .  . 2    2 .  . 2 w 2  .  2 w 2  . -Ms3/+Ͱ2+ 9014762 "'-   2 w 2  .3  2  ww  2  MS3/+2ͱ+901647 &4?62"/ w 2   .  2   2 .  . 2M 3S /3/+ 9014762"' "/M    2  ww  2S  .  2 w 2M-3s/Ͱ 2/+9014?62 62"'M 2    2 .  . 2 w 2  . />/ 3#Ͱ#Ͱ,/0/ְ Ͱ '+ ͱ1+'  $901463!2#!#!"&54>5!"&3!2654&#!"^B@B^^B && B^ @   @B^^BB^%Q= &&. aa^(a^(!Cb+@3Ͱ82/03Ͱ(2D/ְͰͲ +@ +"+=Ͱ5Ͳ5" +@5- +E+ 9=5,90154>;2+";2#!"&%4>;2+";2#!"&Qh@&&@j8(PppPPpQh@&&@j8(PppPPphQ&&j (8pPPppPhQ&&j (8pPPpp!Cn+03Ͱ82/@3Ͱ&2D/ְ Ͱ Ͱ/ +@ + "++Ͱ+<Ͱ^^^gggxTTxTpppjKKjK\BB\BB//B/hP88P8  /Ͱ /ְͰͱ +01$  $aa^a^,A&/Ͳ& +& +@&* +& +@ +-/ְͰ ͱ.+&990147623 #"&5465654.+"'4&ɢ5  #>bqb&4f4&mǦ"  #D7euU6 &&@LX.+ͰK/V3EͰP2>/73Ͱ2;  Y/ְ'Ͱ'B+HͰHN+TͰT4+ͱZ+HB> 99N9< $9T7 99EK4'$9 ; $90147&5472632>3#".'&7;2>54&#""'&#"4>2"&$4>2"&3lkik3=&\Nj!>@bRRb@v)GG+v=T==T=g=T==T=RXtfOT# RNftWQ|Mp<# )>dA{ XK--KXx PTDDTPTDDTPTDDTPTDD,V+Ͱ!/ Ͱ)/-/ְͰ%+ Ͱ +ͱ.+ %!9 9 !$9)%9015463!2!2#!"&73!2654&#!"&=4&#!"\@\\\@\8((88(@(88((8\\ \@\\(88((88(@(88(u3Ey+6Ͱ@/"Ͱ2(/ Ͱ0/F/ְͰ,+ Ͱ #+Ͱ=+ͱG+,49 (9#'9@699 (+90,9015463!2!232#!"&7>3!54&#!"&=4&#!"3!267654#!"\@\ \6Z.+C\,D8((88((8+5@(\&5([\\ \1. $>:5E;5E(88(@(88(#,k#+ #8@+ Ͱ7/-Ͱ#/?3Ͱ;2/A/ְ Ͱ +!Ͱ!:+>Ͱ>+ͱB+! %+$9:,-67$9> /3$9#- (1$9 $901$  $ >. 462"&676267>"&462"aa^NfffKjKKj9/02%KjKKja^ffffjKKjK/PccP/yjKKjK #8@+ Ͱ1/'Ͱ#/?3Ͱ;2/A/ְ Ͱ +!Ͱ!:+>Ͱ>+ͱB+! 83$9:&'01$9> /*$91,5$9' 99# $901$  $ >. 462">2&'."'.462"aa^NfffKjKKj9%%20/KjKKja^ffffjKKjK3yy/PccP/1jKKjK '/7+ Ͱ&/Ͱ//63+Ͱ22/8/ְ Ͱ )+2-Ͱ-1+5Ͱ"25+ͱ9+-) $951 $9& $9+/ $901$  $ >. 463!2#!"462"$462"aa^Nfff&&&&KjKKjKjKKja^ffff4&&4&jKKjKKjKKjK3;C] +37Ͳ +Ͱ;/ͰCͰ+D/ְͰA+ͱE+A !48<$9C  %&/>$9013!2#"'##";;26=326=4&+54&+"#"264&"6264&",,ܒlKjKKjKjKKj,,XԀjKKjKjKKjK+7CO[gs +Ͱ/A33ͱ;22*/Yq$3#ͳSk$26/Me}$3/ʹG_w$2//ְͰ+ ,22Ͱ22'ͰD+82KͰKP +WͰW\ +cͰch +oͰot +{Ͱ{ +Ͱ +Ͱ>2+2Ͱ2 +@ ++ ͱ+015463!2#!"&7!!54;2+"54;2+"54;2+"543!2#!"54;2+"54;2+"54;2+"54;2+"54;2+"54;2+"54;2+"54;54;2+"54;2+"K55KK55K```````````````````p```5KK55KK5`````````````````````````@?V0/JͲ0J +@0< +7/BͰO/!ͰT/W/ְ Ͱ Ͱ +@Ͱ@L+*ͱX+@:9L!07$9*%.99B7@HL999!OMRV99901462+"&5.47>32327676#"/.#"#"'&7632327#"'.#"@KjK#@##WIpp&3z # ڗXF@Fp:f_ 7ac77,9xR?d^5KK5#::c#+=&>7p #'t#!X: q%\h[ 17@?EKjr0/UͲ0U +@0< +7/LͳCL7+HͰp/!ͰI/s/ְ Ͱ Ͱ +@ͰF2@W+m2*ͱt+@:9W!07BHLk$9*%.99L7@SWXZ$9HF[ejklm$9ph9!JKnr$901462+"&5.47>32327676#"/.#"#"'&76755675323275'5&'. #"75#"'@KjK#@##WIpp&3z # ڗXF@Fp:f_ ͳשfk*1x8 2.,#,쩉-!5KK5#::c#+=&>7p #'t#!X: `eov:5 \t-  |*[ 3$"+%/&+"9901647 &4?62"/5463!2#!"& w 2   .  2i@   2 .  . 2i@@-S$94762 "' >/.$47 &4?62"/-   2 w 2  .u >  > I w 2   .  23  2  ww  2      2 .  . 2;K< 1Bi7I))9I7 !% %!bcB/4 <B&67632#"'.5!"   ( ,( )##@258++ 36Ͱ2+6 +@+& +0/43Ͱ20 +@ +29/.ְ23Ͱ 2.3 +@. +3)+72"Ͱ2") +@" +2:+)34699"9063899901546;546;2!76232++"&=!"&5#"& !!S  S-S  `SS3;CK7+2Ͳ3+0+K/ͰC/ L/ְ25Ͱ<25 +,Ͱ2,9 +@2/Ͱ 2/+EͰE +$Ͱ$I +!ͱM+,5 12$9/)9(999$E99K7@ !:=>@F$9 5.5462"&6264&"264&"264&"4,,4pp4,6d7AL*',4pp4,DS,4pp`8P88P88P88PH8P88P@4Y4Y4PppP4Y%*EY4PppxP88P8HP88P8P88P8 '6B]iw4+Y GͰ /Ͱ/{Ͱ// ְͰ7+>Ͱ>^+eͰeK+Tͱ+7@ "#,/0$9^>CD$9KeNOYjkuxy$9 4,:;CDKT$9"#NO$9{ ghku$901463!2#!"4?632&#"&'&4762#"'462"&7?654'7#"'&462"&4762"'463!2#!"@USxySN('#Tp   YR#PTUSxyS    7@xSSU#'(PVI   i@'(VvxSSUOW@?   `,<T:+1Ͱ#/Ͳ# +#) +=/-ְ26Ͱ2 6-+ ͱ>+6-#99 9#1 9901&7!2+"&=467>54&#"#"/546;2+"&c0PR'G,')7N;2]=A+#H    >hS6^;<T%-S#:/*@Z}g.H+Ͱ2/Ͱ,/#//ְ2Ͱ'2 +@ + +@ + 20+01=46;#"&=463!232#!"&5463!2#!"&&@@&&&@&&&&&&&@&&&&&&&Z&&&&b2+ /ְͰͳ+Ͱ/3Ͱ2!+01&63!2#!"&'5463!2#!"&b%@%''&&&&@&&&&&&&&k"G+3Ͱ2/3Ͱ2@+EͰEBͰ-/6H/*ְ9ͰC2*9 +@*# +E29AͰA/I+E $9@#9>9-(1999901353#5!36?!#3#/&'#4>54&#"'67632353!'&Ź}m 4NZN4;)3.i%Sin1KXL7~#& *ا* @jC?.>!&1' \%Awc8^;:+54&#"'67632353!'&Ź}m 4NZN4;)3.i%PlnEcdJ~#& *ا* @jC?.>!&1' \%AwcBiC:D'P-+/+01&6763!2#!"&'7!! &:&? &:&?uPmK,)""K,)"5hH+_37/1ͳ,17+<i/ְVͲV +@V[ +V +ͳ +ͳK+BͰ!2P +>Ͱ(2j+S99> FH$9B&97H>NY[$9<PV99,4S99011327654.54632326732>32#".#""#"&54>54&#"#"'./"'"%_P%.%vUPl#)#T=@/#,-91P+R[YO)I-D%n  "h.=T#)#lQTv%.%P_ % #,-91P+R[YO)I-D%95%_P%.%vTQl#)#|'' 59%D-I)OY[R+P19-,#'3#+3Ͱ%/3 Ͱ2/,4/ְͰ(+/ͳ/(+$Ͱ$/Ͳ$ +@ +$ +@$! +/ +ͱ5+/( 99 ,199,2 $9015462 =462!2#!"&463!5&%46  &&4&r&4&&&&&&&&&&4&&4&G s7CK.+"3)L/8ְ?Ͱ?/+"Ͳ"/ +@"& +/" +@/, +"+ͱM+?84B99/2ADE$9"H999 K9999.)45990164762#"'32=462!2#!"&463!5&'"/5462&%4632   R 76`al&4&&&&&}n  Ri&4&e*f"3  R  `3&&&4&&4& D R&&57&5462!467%632#"'%.5!#!"&54675#"#"'264&"  8Ai8^^.    @ o&&}c ;pG=( ]&4&&42 KAE*,B^^B! `  ` fs&& jo/;J!#4&&4&$ %-(-/ ./+ְ ͱ/+ + 9 - 90167%676$!2#"/&7#"/&264&"$ {`PTQr @ U @8P88PrQ P`  @U @P88P8+ $3/33/ְͰ+Ͱ + ͱ+6>+ >+ >+     ... ......@9011!2!6'&+!!̙e;<* 8GQIIc@8 !GG + /Ͱ/!/ְ ͱ"+$901$  $2?64' 64/&"aa^4f3f4:a^L4:f4334f: + /Ͱ/!/ְͱ"+$901$  ,2764'&" aa^,f4:4f3a^4f4f4 //!/ְ Ͱ +ͱ"+  $901$  $27 2?64'&"aa^,f4334f:4:a^4f3f4: / /!/ְ Ͱ +ͱ"+  $901$  $2764/&" &"aa^,4f44fa^4:4f3f@ /Ͱ/3Ͱ2/3Ͱ2/+6?d+ . ?$+ . +  +++ ....@  ............@01!%!/#35%!'!7†/d jg2|bx55dc  @h/3Ͱ 2 / 3 Ͱ 2/+6>j+ .  +  +.. ......@017!%!!7!!  G)DH:&H;KdS))MUJ+?3 +.+/,3Ͱ$2U/V/ ְ2.Ͱ#2O. +Ͱ/OͲO +@ +S. + Ͳ S +@ ) +W+ E9O9.S9 D9J6BG$9U P999011463!2#"&=46;5.546232+>7'&763!2#"/ $'#"'&264&"`dC&&:FԖF:&&Cd` ]wq4qw] @&4&&4`d[}&&"uFjjFu"&&y}[d ]] 04&&4&#`!+Ͱ2/ Ͳ +@ +$/ְͲ +@ + +@ ++ ͱ%+ 99 901546;4 +"&54&"!2#!"&8( r&@&Ԗ(88(@(8`@(8@&&jj8((88 #+3+ Ͱ#/'Ͱ3//Ͱ+/Ͱ/4/ְ Ͱ +%Ͱ%-+1Ͱ1)+!Ͱ!+ͱ5+1-@ "#&'*+$9/3@  !$%() $901$  $ >.    6& 462"aa^Nfff,,X>aԖa^ffff,X>ԖԖ/9 /,33ͱ$220/ְ Ͱ +Ͱ +)ͱ1+01546;2+"&%546;2+"&%546;2+"&8((88((88((88((88((88((8`(88((88((88((88((88((88/3 +Ͱ/Ͱ-/$0/ֱ 22 ͱ(22 ͱ1+01=46;2+"&546;2+"&546;2+"&8((88((88((88((88((88((8`(88((88((88((88((88((88+EJ /!ͱ622A/F/ְͱ,22;+ ͱG+;$4999A!).999015463!2#!"&264&"';26'&'&;276'&.$'&www@wKjKKjK    \ f ww@w jKKjK  ܚ H     f  / //ְ Ͱ +ͱ+  $901$  $%32764'&aa^2  ! a^% @J@%65+/0/%ְͱ1+% 901476227"/64&"'62764'&" 6%%k%}8p8~%%u%k%~8p8}j6j6[<<k%%%}8p8}%k%t%%~8p8~4j4j-<( /Ͱ/ /ְͰ+ ͱ!+015463!2#!"&3!26=4&#!"www@w&&&&ww@w&&&&/: +Ͱ-/$Ͱ/0/ְͰ+ ͱ1+ (9901463!2#!"&73!2654&#!"5463!2#!"&w@www^B@B^^BB^@ @wwwwB^^B@B^^B@@@/+Ͳ +@ +/ְͱ+99017&?63!#"'&762+#!" @(@>@(@ %% $%-/Ͳ +@ +/ְͱ+ 990163!232"'&76;!"/&  ($>( J &% $( /Ͱ/%/ְͰ+ͱ&+015463!2#!"&2764/&"'&"www@wf4ff4-4fww@wq4f4f-f%/F /Ͱ./0/ְͰ*+ͱ1+*"&$9.% '$9015463!2#!"&%! 57#57&76 764/&"www@w  `448.# e \Pww@wW  `844` #  \P)( /Ͱ#/*/ְͰ+ ͱ++015463!2#!"&27327654&#!"www@wf4 '& *ww@w14f*&')5C /Ͳ +@ +./6/ְͰ'+ͱ7+."'99*9015463!2#!"&3276'7>332764'&"www@w ,j.( `'(wƒa8! ww@w  bw4/*`4`*'?_`ze g /Ͱ//ְ Ͱ +Ͳ +@ ++ͱ + $9 $9$901$  $ >. -aa^(a^(1-< /Ͱ/./ְͰ+ ͱ/+-&99")99015463!2#!"&%3!2654&#!"63!2"'&www@w   @ ((Bww@ww    ###@-< /Ͱ/./ְͰ+ ͱ/+!(99$+99015463!2#!"&%3!2654&#!"&762#!"www@w   @ @B@((ww@ww    C#@##-< /Ͱ/./ְͰ+ ͱ/+ '99$+99015463!2#!"&%3!2654&#!"476'&www@w@##@##ww@ww(B`BZ+@Ͱ^/<3Ͱ32/03Ͱ(2%/a/b+^@I9%901546;&7#"&=46;632/.#"!2#!!2#!32>?6#"'#"& BCbCaf\ + ~2   }0$ #  !"'?_ q 90r p r%D p u ?|=+Ͱ/2= +@4 +/-3Ͱ%2!/@/ְ2/Ͱ$2/ +@/* +/ +@ +/0+8ͱA+0/99899!9901=46;#"&=46;54632'.#"!2#!!546;2#!"& a__ g *`-Uh1  D  ߫}   $^L   4b|W/ Ͱ=/%c/ְ@Ͱ@Z+!2SͰ)2S+Oͱd+@9Z9S =G999H9O1899 WR[99=46O$9%!*9901?676032654.'.5467546;2'.#"+"&=.'&4g q%%Q{%P46'-N/B).ĝ 9kC< Q 7>W*_x*%K./58`7E%ǟ B{PD  cVO2")#,)9;J) "!* #VD,'#/&>AX2 ,-3>)9+ /.3Ͱ&2/Ͱ$?/@+01546;267!"&=463!&+"&=463!2+32++"''& pU9ӑ @/Ԫ$  ] VRfq f=Sf o E[.+3/(3:Ͱ 2=/3DͰ2F/1ְ;2*Ͱ2*1 +@* +$21* +@1@ +62G+*1 9901&76;2>76;232#!!2#!+"&5!"&=463!5!"&=46;  % )   "       PW&WX hU g Jg Uh 08l)+./#3Ͱ2/3Ͱ128/9/,ֱ22%ͱ122%, +@% +,% +@, + 2%5+ͱ:+89901546;5#"&=46;463!2#!!2#!+"&=#"&!264&#! @jjv u~v||PT]aen^I+@3N/nDEMU]f=$3ͷd4RS^_c$2/e3QT`ab$3ͳ!*$2 +@ +$22o/p+6+ L V=+ T.\a FD+ `.Cb i=+ k"> )L+L+L+V+k!k"+>*>)+3>)+4>)+=>)+`D`C+FEFa+ML+QV+RV+\S\T+UV+\]\T+F^Fa+`_`C+bcbi+kdk"+ek"+bfbi+3^+ gbi+hbi+=+ klk"+mk"+nk"+gbi #9h9lk" #9m9@")>CFLV\gmhikl................@,!")*34=>CDEFLMQRSTUV\]^_`abcdefgmnhikl............................................@NIYj9901546;'#"&=46;&76;2!6;2!6;232+32++"'#+"&'#"&%3746573'#!37465!mY Zga~bm] [o"դѧ u #KQ#F"!QN@@X hh @@h h+,83H\+(+33Ͱ42 +@/ +)2G/KͰ /\3 Ͳ222 +@  +2]/ְ24Ͳ-I2224/Ͱ//34*+2)Ͱ2^+/9*47FKZ$9)E9GD9K999 Y901373273&#&+527536353#5"'#"&#%22>54."#52>54.#8o2 Lo@!R(Ozh=ut 3NtRP*H :&D1A.1,GHI$9F:9997D $98.:990176;46;232#"'&5333!53'#36?5"#+#5!76;53!3/&5#" iFFK//Kq   x7  y˱H l` @jjjjjZ sY wh/" "})GR%+HͰ)/ 33ͳ"&$2*/CͰ@2EͰ6/9Ͱ298S/ְ Ͱ 8+*27Ͱ&287 +@8) +7D+#2GͲGD +@G +T+6<$+ &R &%&R+R..%R....@ 989D7!'(/?HI$9G;:99H%9* M$9C+?990176;46;232#"'&333!53'#3!56?5"#+#5!76;533/&5#" iFFK//KYq   x7  yH l` @jjjjZ sY wh/" ")9IYu+&Ͱ27/.ͰG/>ͰW/NͰ2Z/ְ Ͱ J+*:222SͲSJ +@S" +@S3 +@SC +[+ 9J97 $90176;46;232#"'&463!2#!"&55463!2#!"&5463!2#!"&5463!2#!"&" f@@l` @y")9IYu+&Ͱ27/.ͰG/>ͰW/NͰ2Z/ְ Ͱ )+*:J222"Ͳ") +@"3 +@"C +@"S +[+ 9)97 $90176;46;232#"'&463!2#!"&55463!2#!"&5463!2#!"&5463!2#!"&" f@@l` @y"8KV&/3/Ͱ6/Oͱ 22U/Ͱ?/@Ͱ<2@? +@@ +:2W/ְ Ͱ +MͰMA+<Ͳ
+A< +@A? +<R+ ͱX+ 9M*+9K$9A&/G999<6:OU$9R32996/+9O299U 990176;46;232#"'&%4632#"'&'73267##"&733!5346=#32654&#"" m{8PuE>.'%&TeQ,j{+>ID2FX;4l` @i>wmR1q uWrrr :MrL6)?j"8KV?/3@Ͱ<2@? +@@: +&//Ͱ6/OͰU/Ͱ2W/ְ Ͱ +MͰMA+<Ͳ +A< +@A? +<R+ ͱX+ 9M*+9K$9A&/G999<6:OU$9R3299&@ $9/*96+9O29U 990176;46;232#"'&4632#"'&'73267##"&733!5346=#32654&#"" m{8PuE>.'%&TeQ,j{+>ID2FX;4l` @i>wmR1q uWrrr :MrL6)?j@\8 +Z3Ͳ +@ +@/ +]/ְͰ+ ͱ^+015463!2#!"&732654&#"467>767>7>7632!2+".'&'.& &&&%&&%`$h1D!  .I/! Nr7.' :@$LBWM{#&@&&&&%%&&%r@W!<%*',<2(<&L,"rNV?, L=8=9%pEL+%@\0/ Ͱ 2 +@K +]/ְͰ+ͱ^+013!2654&#!"4632#"&46767>;#!#"'.'.'&'.'.& &&&%&&%`&#{MWBL$@: '.7qN !/I.  !D1h$&&&&%%&&%+LEp%9=8=L ,=XNr%(M&<(2<,'*%<!W@r% *2?Sem+ ͰP/0Ln|$3Gͱ22GP +@G +/Ͱ/3sͲAJ222+/.3,Ͱo2$/9ͲX222/a33Ͱ3Ͱ<2/ְͰ9Ͱ1+0Ͳ01 +@0. +10 +@1+ +0@+CͰ; TͰCM+I2LͳfLM+kͰL\+ͳ\+nͰn/ͱp22+Ͱ2x+Ͱ/xͰ+Ͱ2+2Ͱ2+ Ͱ Ͱ/+93?99@0>99C=P99T;$9015463!2#!"& 7>7654'.'&! 753##35#'33273#5#"'&3276=4'&#"542"3632#"'532=4#"3273##"'&5#54762#32746453#"'&7354"www@w A+&+A  B+,A RPJ # JZK35DBCC'%! p3113C@@EC $)  )#!2 $)CCCf"D 54BBBww@wET+<<+TS,;;,W FFY\g7("(-:&&<:&&:443(*54*)$H12%-(rU;&&:LA3  (&"33 !-AS[mw4+^3/ʹ25\`$2/Ͱͱ;v22/Ͱq2!/l3Ͱ/P3ͰU2Z/Gͱy22/ְ.Ͱ.( )Ͱ)/(Ͱ.?+9Ͱ429& %Ͱ%/&ͳB9?+TͰ96+\ͳW\6+LͰ\x+{ͳt{x+nͰn/]k33tͰ{+2ͳ+dͰd/Ͱ +2Ͱ2+2 ͱ+66R+ ",#$"#$,...."#$,....@() $9&%2;99\6GP99{xi`999d999999n99 o999!@ 78@Aik$9)($9Z'990147>76  '.'&3335!33#&'&3273##"'&5#547632#"'&72=4"353276=4'&#"5#632#"33273#5#"'&327676=##"=354'&#"542X;:Y X::Y oidkȀjGDfyd/% .06YYY&CE%%EC&ZVV^Y-06 62+YY''.[[[52. 'EH$[!.'CD'YZt;PP;pt;PP;p9^qJg1%=6* lRP%33%PQ%33&?FFEE077II86-CC!+} 7>%O%35 1 3 $EWgO%33%O.DD.{'&72'&76;2+%66;2+"'  ( &' P *o"-J. -Z-#7,(+ Ͱ/Ͱ58/9+($/999015463!2#!"&;274'&+"%;276'56'&+"www@w~}   ww@wc $`" j!#  #/$+$0/ְ ͱ1+ 99014>7>76  '.'.32764'&jGGkjG~Gk~!"! lAIddIAllAIddIAt& @J@&@ / ֲ222Ͱ2!+01 5577'5 @RVVWRW.\?il``l1~~ # + Ͱ /Ͳ +@ +2//3/#/!/$/ְͰ++++ + ͱ"+%+6&....ɰ6&....ɰ6&! . !.#"."#.ɰ6@ $99999#99013!3!'75%77777yx#C j''MaM}|yjC#A$VUG%/? /Ͱ/)Ͱ/$34Ͱ./Ͱ<@/ְͰ"+'Ͱ',+Ͱ+72 ͱA+'"$9,0?9999)"'+$94&,99015463!2#!"&73!265##"547#$3264&#"%;26=4&+"tQvQttQQt#-$܂"((((EvQttQQttz##?D~|D? =(())8 /Ͱ2/3 /ְͰ+Ͱ+ ͱ!+015463!2#!"&264&"264&"www@w||||||ww@w||||||| //+$901$  $37!3aa^g^h h^5a^2-2P#<P\g<5/(Ͱf/ah/cֱi+(5/;99f$&)-STe$9a 9901>767$%&'.'.? 7&'.'&7>7.'$7>'.676'&"8$}{)<U,+!  #7 ,$Vg.GR@&\74~&p )4 2{ "8 eCI0/"5#`# ## /1 "[\kr,y9R ;&?L .AU`iGT/O3EͰH2j/VְbͰb9+ ͱk+9b=>L]ef$9 $;99ETL9015463!2#!"&7>776'&'&7>746&' '>76'.&676&66'4&www@w$ i0 +p^&+3y/" h . ."!$2C',,&C7-F XjM+'TR$ww@wD$4" P[ & 57!? "0>8Q.cAj'jj#"p1XRMBn \i6-+.N#b/Ͱ /3 Ͳ +@  +$/"ְ Ͱ2 " +@ +" +@" + Ͱ/%+9 9 90156767673!!327#"'&'&'&5N[@@''l '2CusfLM`iQN<: 67MNv|v$%L02366k3\ /Ͱ!/(Ͱ2-/4/ְͰ'++2 ͱ5+399'-9 )999!9(9015463!2#!"&3327675#"'&'&5!5!#www@w*+=>NC>9MXV3%  10Dww@wlN+*$% $8c'#Z99*(@/ְ ͱ+ 90176;46;232#"'&    & /ְͱ+901&7632++"&5#  ^  c  &  @//+901476!2#!'&@  & } b  ^ //+ 9015463!546'&=!"&&      q&8M/Ͳ +@# +2 +@ + 29/ְͱ:+ '1$99990147632327632#"'&#"#"6767qpHih"-bfGw^44O#AY'T1[VA=QQ3KJ?66%z䒐""A$@C3^q|}} !"lk) =KK?6  (/ְ2Ͱ2+ 2 Ͱ2+01!%!%VKu-u5^mf}~ "=EM["/ͰAͰH2\/ְͰ#+ 2&Ͱ"29&#+3ͳ+&#+0Ͱ0/+Ͱ&N+Vͱ]+&#>BFJ$93999+099ADL$9014632"&467'&766276!+"&=##"&5'#"&264&"264&"4632#"&<+*<;V7>5'&7>.'&'&'&7>7>767&'&67636'.'&67>7>.'.67'.'&#"'.'.6'.7>7676>76&6763>4'>&4.'.'.'.'.'&6&'.'.6767645.'#.'6&'&7676"&'&627>76'&7>'&'&'&'&76767><&'&23256&'&4723#76&7?4.6>762674.'&#6'.'. "  V5 3"  ""#dA++ y0D- %&n 4P'A5j$9E#"c7Y 6" & 8Z(;=I50 ' !!%&&_f& ",VL,G$3@@$+1$.( *.'  .x,  $CN7  J#!W! '  " ';%  k )"    '   /7*   I ,6 *&"!   O6* O /     Wh   w*   sW 0%$  ""I! *  D  ,4A'4J" .0f6D4pZ{+*D_wqi;W1G("% %T7F}AG!1#%  JG 3   J  <   mAe  .(;1.D 4H&.Ct iY%  "+0n?t(-z.'< >R$A"24B@( ~ 9B9, *$        < > ?0D9f?  .Y  G   u7   $37C[bu'+ Ͱ/ͰB/c/ְ Ͱ S+ͱd+S @  %)468@D\a$9'+Sb^$9FIN$9B"46:DU$901$  $>?>7&'!7 %&'327&#63"3>7&#">2&'>7&aa^^XP2{&% .0x||*b6~#sEzG<L $MFD<5+  CK}W)oa^2|YY^D 1>]yPեA4MWME6< 5* @9IK<^/#Ͳ# +@ +D/ͲD +@ +_/ְIͰ 2IͰ/I +@IS +I(+Ͱ Ͳ( +@(5 +`+I9(@$9 9#9D $99014632632#"'#"$&547&32>54./.543232654.#"#".#"ែhMIoPែhMIoPxIoB':XM1h*+D($,/9p`DoC&JV*x& i55K55q*)y(;:*h )k5555K*x?x*& /8 /#ͰͰ/+30/ְͰ+ Ͱ '+ ͱ1+01463!2#!"&3!2654&#!"3!2654&#!"&&&&  @&&&&19L9/5:/"ְ*2Ͱ2" +@ +" +@"' +"3 7ͱ;+"4589$9014763!2#"'#++"&5#"&5475##"&462"IggI8(3- &B..B& -3(8kk(8+Ue&.BB.&+8뺃%-~ /3Ͳ  + $ + 22@  +2-/)./ְ!Ͱ!+Ͱ' +Ͱ+Ͱ+ ͱ/+(-99+'99),9901463!2"&5#"&5#"&5#"&462"pPPp8P8@B\B@B\B@8P8 PppP`(88(`p.BB.0.BB.(88+ !"/ְͰͱ#+ 9901$  $ >&'&#"'.aa^]^/(V=$<;$=V).a^J'J`"((",9I&?'&767%476762%6'%"/'&5%&2>4.", $ $ " $ $  ܴ  [՛[[՛k `2 ^ ^ ` ` ^ ^ 2`՛[[՛[[1:$+Ͱ)/2/ְͰ-+ ͱ3+ -/9)'90146$763276#"$&732$7#"$547s,!V[vn)^zf킐[68ʴh}))Ns3(zf{n 6<@+&/Ͱ*Ͱ /,/-+*#901463!2#!"&463!2#!"&3!264&#!"@&&&&@&&&&@&&&@&&&&&&@&&44&&4& `BH/+,3 +A/3Ͱ2./ Ͳ . +@ +2C/FI/@ְ2.Ͳ@. +@@ +@@ +.-+Ͱ2- +@ +@ +J+.@ 5>CE$9- &FH$9 /&5>$9C99F990146;'&462!76232+"/##"./#"'.?&5#"46  &&4L4&&&C6@Bb03eI;: &4&&4&&4&4&w4) '' 5r}G(/ְ1Ͱs21 +@ ++1z9014?63%27>'./&'&7676>767>?>%63#&/.#./.'* 46+(  < 5R5"*>%"/ +[>hy  @ 5d)(=Z& VE/#E+)AC (K%3?JUkc"/*Ͱ1/Ͱ}/oͰj/Y/dְ_ͱ+_de91*@ >8BNTa$9 0dev{$9o}|9jp9901476$6?62 $.776$'.$&7>'&676&'&7676&'&&676.76&'.&676'.76&&YJA-.-- 9\DJՂ % Q//jo_--oKDQ#"N  {WW3' 26$>>WCw%`F`F_]\df`$E ""F!I  B8/Ka`s2RDE5) %^{8+?` r 2/ְͰ+ͱ+ 9 999014$7&>7#"&$̵"#ÊI$~EacxWW^ czk8j/Ͱb/[Ͱ l/,ְ@ͱm+@,S9[ U]g$9014636$7.'>67.'>65.67>&/>./"+f$H^XbVS!rȇr?5GD_RV@-FbV=3! G84&3Im<$/6X_D'=NUTL;2KPwtB X^hc^O<q&ռ ,J~S/#NL,8JsF);??1zIEJpqDIPZXSF6[?5:NR=;.&15Pt=   ' /3Ͱ /Ͱ/Ͱ// +0175!+!"&5!!5463!2sQ9Qs**sQNQsBBUw wHHCTwwTC 1s /Ͱ//Ͳ/ +@/* +/ +@! +/2/ְ Ͱ +ͱ3+  %$9/ $9%&99 $901$  $ >. 5463!54632#"&=!"&aa^( ` ?   a^(     1s /Ͱ*/!Ͳ*! +@*. +!* +@! +/2/ְ Ͱ +ͱ3+  %$9* $9!99 $901$  $ >. 47632!2#!#"'aa^( @  `   a^(d @    ?/< /Ͱ/0/ְͰ+ ͱ1+ (99%,99015463!2#!"&%3!2654&#!"47632#"'www@w   @ &&@ww@ww    B@ && @ Z /Ͱ/Ͱ/ /ְ Ͱ +Ͱ+ͱ!+ $9  $901$  $ >. 462"aa^(Ԗa^(ԖԖ]6/+/ Ͱ3/&Ͱ%/"Ͱ!/7/ְͰ+ͱ8+6+ !.6!6&!"!&+%!&+6..!"%&6.....@99 993/*+$9%&9"9! 9014732>'#"$&7>32'!!!27#"'!"&'Ѫz~u f:лV6B^hD%i(: ((%@*>6߅~̳ޛ 3?^BEa߀#9cr#!KL/ְͲ +@ +M+015463!2#!"&66767676'&6'.'&'.'&www@w C1 $$*=+T"wh%40C>9PC/+,+  /9F6(ww@w$)7 .3c M3IU/A*7U1.L4[N .QAg#%@) D:+E/=ֳ>$2+ͳ!"*$2+= +@+' +2=+ +@= + 2+.+5ͱF+6+ #?)+  #+ +++! +"#+?*?)+>?)+@ !"#)*>?................ #)?........@0154?5#"'&=4?546;2%6%66546;2+"&5#"'& wwww `G]B Gty]ty cB Cr +ͰA/63$Ͱ.2A$ +@A< +$A +@$) +/D/ְͰ?+%28Ͱ-28? +@83 +?8 +@? +8+ ͱE+01463!2#!"&73!2654&#!"5463!46;2!2#!+"&5!"&w@www^B@B^^BB^`@`@ @wwwwB^^B@B^^B@@`@`'7HP[./+Ͱ!/3Ͱ 2  ͳ!+&ͰF/DQ/LְͱR+ JM99&999FLO99901467&546;532!!+5#"&547&327!"+323!&#64'M: @nY*Yz--zY*n@ :t9pY-`]]`.X /2I$ tkQDDQ54!/@@3,$,3@@/!@&*0&& !P@00$pRV46?'&54632%'&5463276327632#"&/#"&/#"&546?#"&%%7,5TS]8T;/M77T7%>54&#!"www@w8(@(8!"5bb./ * =%/' #?7)(8ww@w7(88(#~$EE y &%O r    O"):8%_gqzh+ /Ͱ]/&I33)Ͱ/r/ְͰk+oͰo+ ͱs+k@   #&,`dh$9h#`df$9) @ "BMUam$9016$  $& $6&$ 47&6$32#"67>&&'&67>&"&#"%654'LlLe=Z=刈2CoiSƓ i 7J ?L.*K  Px.* ~p;_lL刈=Z=刈_tj`Q7  $ki'<Z :!   @! yy,ik*%E/3Ͱ2/ְͲ +@ + +ͱ+ 9990146$7%&$&57%7&]5ň%wnj&P'!|OzrSF 0y+Ͳ!%)222+ͳ#'+$2 /1/ְͲ +@ +2 +#Ͱ#$+'Ͱ'(++Ͳ+( +@+0 +22+$# 901463!2!5 ##!"&5546;!3!3!3!32))) ));;)&&&&@&&@ (6]4/-Ͱ /7/ ְ#2Ͱ2  +@  +8+ !'$9-4!#$9 %99'*/$9014762"'%+"'&7&54767%27% $&` ` t+8?::  ::A W>4>֬.`."e$IE&O &EI&{h<EvEEvm!"/ְͱ#+99901327>7327&#"&m:2+D?*%Zx/658:@#N >+)@ (oE=W'c:= E(o0La,/7Ͱ /SͰ]/3b/ְMͳ1M+Ͱ/1ͰM+!Ͱ!X+ͳ<X+'ͱc+M ,]999! 7EGS$9X9$999 7!'G$9]S990174676%.547#"&5467>3!##"&'&732>54.'&#"3267654.#"oYJ .H?LpKL1FE1@Z[@1G렄:$/Kce3:k[7'9C!5goS6j+=Y4%Q5">j@*Q.Q.R)A)(-R6B@X?ZHsG;@"$ECPN[RzsS`;v8\;)4^>0$/. 0$8].ggR4!8g;}R'!;5>R]q|z+/EͰo/dͲdo +da +h2[/z3VͰt2>32#"&'%632#"$'.547.767&#" $7>4&'&$ 462#"&462;2762+"'462#"&264&"654&#"^SAX[]8MmmMLmtG@W^>4}|0:M31$.>Wewpt+H+tpwwpttpSpQQ89Rj MM  ccSpQQ89R@Z@@Z5/9W>1^7R2>mnlMJ:^>h!yTRWWRTz%e;C,hWʺIKQQKIʹIKQQKI9RR98PP! MM ! cc9RR98PPoZ@@Z@i.G>WAI`ht /Ͱ^/QͲQ^ +QN +V2I/g3EͰc2%/?3.Ͱr/lͰ3/u/ְͰͰC+GͰGb+fͰfi+oͰo+ Ͱ "Ͱ"/v+C=?999GJO99b;)999f*UYX$9i,6+999o%'3.$99 09EI$9%"'=$9.();<$9lr+016*$9389015463!2#!"&32$654'>54&#"&'3264&#"'&&#"462"4762;2762+"'$462"4632#"&'!#,H3<&SG12HH2$< _$93HR4J44J1{z3A@:4J44J****~%=baab?'3I0k 12FGdH)!6 m+IJ44J633@@J44J6V**** *< /Ͱ-2 +@ + /Ͳ  +@ 6 +%2=/ְ Ͱ (+#Ͱ#++Ͱ2+9+23Ͱ30+ͱ>+#( 999 99+-993 990.9 )1<$901$  $32654632754&""&=#26=##"&='aa^rsRQsOpoOx|PrrRz~{]0/.3Ͳ +@ +)2/ 1/ְͰ+Ͱ+2#Ͱ2#(++ͱ2+9 9(#.9%&99  !"$901!2654632'54&"#"&%7265!#"&H7>3263232654.547'654'63276.#&#"'&547>'&#".'&'#"&%>327>7?67>?.'.*#"3>32#"'>;?757)  //7/ D+R>,7*  2(-#KcgA+![7>7>7 $&32>67>54.#"#.67>76'&#"'&#"767>3276'&'&#"';RKR/J#=$,9,+$UCS7'|ՀMLCF9vz NAG#/  -!$IOXp7s_"kb2)W+ rJ@    #    5/1Y|qK@ %(YQ&N EHv~\lshp4AM@=I>".)x.--ST(::(Y ! "1 [   / ,<ZxX-/U3%ͰC2%- +@%" +F2y/uְS2bͰL2bu +@be +I2z+buFPh999%-)I999015467&6?2?'#"&46326'&"/.7.?>>32'764&"?#"&'&/7264/YE.A %%%h%AUpIUxxULs T@ %hJ%D,FZCV sNUxfL.C %Jh%@/LexUJrVD %hJ%NHpVA %h&%%@.FZyUybJ/@ %Ji%CWpC-KfyUMt UC %hJ%@U sMUy^G,D %Jh%cv++3/Ͳ +{ +s/k/ְͰ+Ͳ +@ ++6+ :=1'+ (1'+++ :<:=+<:= #9(1' #9(1:<....(1:<....@99@ &7MSdnx$9 9999s@ c@I$9kAED$9016767672,32%#"'47%67>7>7&'&'&'>76763>7>&/&'.'767672#&'&546323267>7''+"&'7'7j+.=;. &JlLDf' % :/d B 4@ } ,+DCCQv!0$ && !IG_U% +6(:!TO?=/f-%fdL?6 #nk^/ !X "  ##  292Q41 5gN_     %1$I BS N.|nA '0@P`p4+d33%Ͱ 24% +@4 +=D4 +t33=ͱl22MT4 +33Mͱ|22(]4 +33(Ͱ0//ְ Ͱ +1ͱAQ22(Ͱ18+HX22aͱq22ah+x22ͱ22+22!ͳ)!+ͱ+./990(90146;2+"&%463!2#!"&!#"&=!;26=4&+"5;26=4&+"5;26=4&+";26=4&+"5;26=4&+"5;26=4&+";26=4&+"5;26=4&+"5;26=4&+"^BB^^BB^8((`(:FjB^(8``@B^^BB^^B(8(`("vEj^"8(/?O_o/?463!2#!"&;26=4&+"5;26=4&+"5;26=4&+"5;26=4&+"5;26=4&+"3!26=4&#!";26=4&+"5;26=4&+"5;26=4&+"5;26=4&+";26=4&+"5;26=4&+"5;26=4&+"5;26=4&+";26=4&+"5;26=4&+"5;26=4&+"5;26=4&+"5;26=4&+"&&&&@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@&&&&z@@@@@2@@@@@@@@@@@@@@`%k%/!&/ְͲ +@ + #Ͱ+Ͳ +@ +'+ %$9#!$$9!% $901462!762"&5#"&5$462"@8PpP8B\B@B\BDP88P.BB..BB.8$G #3CQf/Ͳ + +"2R/$ְ,Ͱ Ͱ,4+<ͳD<4+KͱS+,$"99499<9 DO$9014632#".4>32#"&#"#"4>32#".4>32#".4>32#"&TMLFTMLFpYv"?B+D?BJM&X=M{<&X=L|<'<{M=X&<|L=X&VFLMTFLMTPwoJPvoVӮvs.= ZY 2+"&7.@UUr_-$$-_r%&&5% /ְ2 ͱ!+0146762"'.-.&,&.$@B@$F@(BB(#<<%]|*.26:>B2C/8ְͰ?2@+ͱD+8<>$9@=9015467%467%62"'%&'"'%.-%-%-%+#+#6#+$*&!@@@@@@!&l@G@,l@`&@&@ @&p@&`$>>׭:ͽ  }:!7;A5+/Ͳ/5 +@/2 +5 Ͱ,/<Ͱ/ͳ?+%Ͱ!/B/ְͰ2+ Ͱ Ͱ "+,Ͱ<2," +,) +C+ 9, 99<)"99 9%9!9015!2#%!254#!5!2654#!432!32673!"!5!!&#"RWu?rt1SrF(N[\Ίensm?vd3ZpC~[R yK{T:֧IMމoy@7+|i%,AEK /Ͱ0Ͱ/ Ͱ6 9Ͱ93ͳK +IͰ&/'ͰB/CͰ/L/ְͰ+&2#Ͱ*Ͱ#+-Ͱ-<+ ͱM+#99<-BDFK$996#99 -<99IK9'?99015463!2#!"&7!2654'654.#!532#532#327##"&5!654&#"75!>32www@w~uk'JT7|wji> I'DH~?F8q ww@wsq*4p9O*sqhOZ^"(LE MM8Bzl5R[e/9Ͱ>/ Ͱ/#ͳV#+Ͱc/_ͰZ/ͳZ+3f/ְ Ͱ  +TͰT\+aͰaX+ͱg+ 06;$9T9a\UVZ$9>999 9#9c%9_@  ) STWX$90146326327>32##"&'#"'327'.546325.#"3264&#" #".264&#"462#"&zUIr19rsswOIr37UCY? @!'G2LI*?YUI+?YY? $G2#(mnnMLGWzXW>=Wy\GrPk\G;@Y=$2G%,Y%,Y~Z  2G [mmm>WXzWW1DV`j /Ͱ_/dͰi/ZͰ"/Ͱ/k/ְͰX+aͰaf+]Ͱ] +ͱl+X$28ER$9fa"Z_$9_&)+PU$9dAC999i@  ,2%5@WX\]$9015463!2#!"&327326?264&#""&#"%.#"4632'&#"676&/632#"4632#"'2654&"www@wL6$ G.2IGffGHel #  G-6L"8(- 07 ((}*: ('88';D10DD01,7L77L7ww@w5L,:D1zefeG,:L^P8 8  9 7P7I`DD`Du'66'&77V->M\-+L+3AͰ2]/^+AL ?B$901'.?67&>7%.'>%67%7.'6?%7&?a0#Ov "N\$> P(1#00/6 'I]"RE<98 1G#9  ($=!F "\HiTe<?}8J$\ 9%d,6?=SVY]C j# %N#" H@)1;C'/33ͳ23$2-'+>3#Ͱ28/ D/%ְ Ͱ22+ %+Ͱ/+ͳ/ %+=Ͱ +ͳA+ͱE+6>q+ 2;q+ 3.4  4;.... 34;.......@-0B9901546;>3!232+"&=!"&=#"&264&"%!.#!"264&"]ibbi]pp`pp`^^^Y @ c^^^]^^]]PppPPppPp^^^e^^^3;EM1+ (33ͳ<=$271+H3-Ͱ$2B/Ͱ Ͱ2N/ְ5Ͱ59+GͰGK+ͱO+6>q+ .<Eq+ =.>>E....<=>E........@5/99,-99G')* $9K$%99!"99B-:L9901546;>;5463!23232+"&=!"&=#"&264&"%!.#!"264&"]ib@bi]pp`pp`^^^Y @ c^^^ ]^^]]@PppP@@PppP@p^^^e^^^ 3S4/.ְ12'Ͱ$2'. +@'! +@' +@' +.' +@. +@. +@. +5+'. $901647#"&47#"&4762++#!#!"&5467!" &&4&&&2 $$ 2&4&4&44&m4&m4&&##& $:P />ͰFͲF +@FB +M/,Ͱ7/Ͱ /Q/ְ%Ͱ%+Ͱ3Ͱ3/R+% 93@   ;I$99>FDI99M0999,(.39997%999$9  901$  $32763232654'&$#"32763 32654'&!"32763232654'&#"aa^) -g+(~̠4#z##ə0  o*a^(*%D= )/IK/%#!| #(* g  s" :NUk8+ /Ͱ//L/?ͲL? +@LD +/V/ְͰ+ ͱW+ 3;CPR$9/8".1;QT$9L#('0M$9015463!2#!"&73!2654&#!"5%>36'&%#!"&463!2&'$'#&7&Q::QQ::QG((((2 84@ao   Ug AU :QQ::QQ:(((( G;.} 0 T@43f= t !-;<JXfuv762"'?432#"5?632#"'?432#"5?4632#"&537632#"'7632#"'74632#"'732?.#"7462"&'7>2"&'732765?4'&"7567632"&/47632632#!.>  C  E  F  )  J  N  O  /!R U     ;  _U`59uu  ~ ~   |   ,                J|   rq "vu )9:+ Ͱ/Ͱ'/ Ͱ7//:/;+99 '990115 $7 $&5 $7 $&5 $7 $&546$  $&ww`ww`ww`bb`ΪTVVTEvEEvŪTVVTEvEEvŪTVVTEvEEvŀEvEEvEEvEEvW\gyQ+/ͰJ/Ͱ/@Ͱ/zͰ-2//ְͰj+8Ͱ8+zͰz+ ͱ+j@ W(*OXZ]dyu$98:nt9992_99z>M99@CJ{$9JQ!$OXZ$9G]99M9@>_99(:dh$9z5nux$9901463!2#!"&7!!"&5!>766767.76;2632#"&'#"/&'&767%67.'&'674767&54&5&'%!&'&'3274'&8((`8(8((8`(8 ^U 47D$    7[!3;:A0?ݫY  A4U3IL38k Cx JL0@(8(`((88H8((g- Up~R2(/{EJ1&(!;  (X6CmVo8%(*\ 9 JQ\/Ͱ/KͰ/R/ְͰ+GͰG+KͰK+ ͱS+6=+ >= !}F+ '*<8>m+ 32,-1+ '('*+)'*+ + <9<8+9<8 #9('* #9)9@ !'*,-238<=>()9...............@ !'*,-238<=>()9...............@J99GHI999K+01:$9./L999%+/16I$9KQ901463!2#!"&7!!"&5!3367653335!3#'.'##'&'35!!&'&'8((`8(8((8`(8iFFZcrcZx @(8(`((88H8(k" kkJ ! k 9 LSn/Ͱ/MͰ/T/ְͰ+MͰM+ ͱU+-./378>$9M9902456N$9699MS901463!2#!"&7!!"&5!!5#7>;#!5#35!3#&'&/35!3#!&'&'8((`8(8((8`(8-Kg kL#DCJg  jLDDSx @(8(`((88H8(j jjkk kk 9 1<C/Ͱ!/2Ͱ3/.3,Ͱ/=Ͱ/D/ְͰ+=Ͱ8 'Ͱ=+ ͱE+ !-/23$9'>9!09932'9=C901463!2#!"&7!!"&5!!5#5327>54&'&#!3#32#!&'&'8((`8(8((8`(8 G]L*COJ?0R\\x48>/x @(8(`((88H8(jRQxk !RY~ 9 #+2+/Ͱ+/'Ͱ/,Ͱ/3/ְͰ%+2)Ͳ)% +@)# +)+,Ͱ,+ ͱ4+)% 9,!9-9+ "999'!9,2901463!2#!"&7!!"&5!57 462"!&'&'8((`8(8((8`(8@pppx @(8(`((88H8(pppp 9  3;?CGKR2+7Ͱ/Ͱ;/(Ͳ(; +@(& +D2AMPU$9X^901463!2#!"&7!!"&5!546;76#"/#"&32764'.3276'.!&'&'8((`8(8((8`(8 WW6&446dd$x @(8(`((88H8( )5]]$59955{{ 9 ,<Ck/Ͱ*/:3!Ͱ12/=Ͱ/D/ְͰ+&Ͱ& +=Ͱ=+ ͱE+=-.9915:>$9=C901463!2#!"&7!!"&5!463!2#!"&%5632#"'!&'&'8((`8(8((8`(8L44LL44L  x @(8(`((88H8(4LL44LLZ  w 9 0@T[/Ͱ/UͰ/\/ְͰ+UͰU+ ͱ]+6?#+ 12:9129:....129:....@&99UBF99DNV999".&'>/.$&?'&6?6/!&'&'8((`8(8((8`(8~ 3  3  ?  ? ; 3  3@x @(8(`((88H8(-- & & U?     &  &` 9 '6h)/$Ͱ/7/ְͰ +!Ͱ!+Ͱ&28+! 9999$)999$)'99 &$901!67&54632".'654&#"327#'. 'XyzOvд:C;A:25@Ң>;eaAɢ/PRAids`W`H( ' gQWZc[-05rn"&*-Q./ְͰ+2#Ͱ'2#,+ ͱ/+$9# "$9,!$)+$9014762"'&?'%%-%% "3,3"",">[ NM[N o")" )) "nngng]xߴ]x#Z+'Ͱ<2./P34ͰJ2X/B3 Ͱ[/ְ$Ͱ$?+ͱ\+$!999? 999999.')9X,H$9 $901467&546326$32#"&#!+.327.'#"&5463232654&#"632#".#"n\ u_MK'oGԨ|g? CM7MM5,QAAIQqAy{b& BL4PJ9+OABIRo?zn6'+s:.z zcIAC65D*DRRD*wya$, @B39E*DRRD*'/7 /"Ͱ&/Ͱ/+Ͱ//8/ְͰ+Ͱ+7Ͱ73+ ͱ9+9999  #(-$97059931499&" #99$'99 14$9+),99/(-99016$  $&7&47' 6&  7'"'627& 6'LlLZ&>ʫ|RRRR«ZZlLRR>ZZZY«|R!Z +Ͱ/3Ͱ2"/ְͲ +@ ++Ͳ +@ +#+99 99014$7 >54' $&_ff_ʎ-ff`-޶Lc@_/d/ְ Ͳ +@  + G+[ͱe+ 9G5;NQ_$9016721>?>././76&/7>?>?>./&31#"$&(@8!IH2hM>'  )-* h'N'!'Og,R"/!YQG54'675#&#"432#"432#"2654&"3&547#6323#3275#"=3235#47##www@w(DL+`N11MZ % N92Z2<)UmQ// +)&')-S99kUeid=R;XYtWW-Ya^"![Y-L6#)|!'(<`X;_"# /Ͱ/3#/$+9015463!2#!"& 3##.'www@wpCWU3D/9$H ww@wFML'b;0bqG9+Iw /Ͱ$9<%(9998 #3>$9014>32#"'.7>32>4."&'&>767&5462#"'#"&'9]v @C$39aLL²L4 &) @.&FD(=GqqrO<3>5-w؜\% L²LLarh({󿵂72765'./"#"&'& }1R<2" 7MW'$  ;IS7@5sQ@@)R#DvTA ; 0x I)!:> +)C 6>&8CO[6/GͰS2M/Y3+Ͱ$/A3Ͳ$ +@$ +\/ְͰ(+Dͳ9D(+"Ͱ"/9ͰDJ+PͰPV+/ͱ]+"999$9D(>9PJ +6$9V49G6'/24$9M(9+9$ <$9014$32&#"#".'7$3264&#"6$32'#"$3264&#"32654&#"32654&#"MŰ9'#!0>R H|B+)22)+Bu7ǖD[B+)11)+B-(33(--'44'-ZNJ '31R23uWm% '31R23-,,--,,-&7632#"'%#"'.5 %&"! ; `u%( (!]#c &76#"'%#"'.5%&7 ##!!  (%P_"'(!7+4Iy/ Ͳ  +  +G/9Ͳ9G +@9> +)/ J/:ְCͲ:C +@:5 +C%+ͱK+C: ) $99G$99)% 12$9 99014766$32#"$'&6?6332>4.#"#!"&546;46;2#!"&('kzz䜬m IwhQQhbF*@&@@*eozz   _hQнQGB'(&@`@ D+ Ͱ//ְ Ͱ +ͱ+  $9$901$  $ >. aa^Nfffa^ffff>g/BHm333bͲ7654'&#!"#"&#"#"&54>765'46.'."&>..**"+8#  #Q3,,++#-:#"$$ /:yu #3=GWak:/^334Ͳ4: +@4 +@4Y +1/(Ͱ /ͰU/LͰb/fͱB22bf +@b +@b> +l/ְ2Ͱ"2=+>26ͰF26X+b2[Ͱj2m+= $%$9X6-,HI$9015463!2#!"&!+"&46;25463!2#!"&!+"&546;25463!2#!"&!+"&546;28(@(88((88(@(88((88(@(88((8@(88(@(88`.` @(88(@(88x ` @(88(@(88`.%Q/Ͱ/ ͳ +$&/'+$!99"$999 $9  9901632%&546 #"'632 &547%#"~\h ~\h\~\~ V VV V5j /ͰͰ/(Ͱ4/Ͱ-6/ְͰ+*2 ͱ7+"999!$9("%994&*2$9015463!2#!"&327264&#"'64'73264&"&#"www@w}XS>~}}XT==TX}}~>SXww@w}9xX}}~:xx:~}}Xx9/>JXgsNr/kt/ְͰ2?+Fͱu+ )03$9? 47;$9F9kr 9016$327627 $&327>7>.4762#"/5462"&4762"/&4?62#"'46;2+"o@5D.D@Yo1 *"T0l,  Z [E  [  Z Z  [ ``1oY@D.D5@ooS0 (T" 02 ,l [  Z)`` Z  [ [  Z =BH!_<ϙwiϙwi  U3U3]yn2@ zZ@55 zZZ@,_s@ @(@@- MM- MM @@ -`b $ 648""""""@N@ ,@  mo)@@   'D9>XRX8` 2  r ` xJT6(R@z (R.j !֜8~*pž:vܠBT袨(Ȧ|4ȬHбT ̴ffҸ>d0R6N(*|.vƒdȜzʸ8̼͚&n>Ҡ*x lVrݤބ2"2v0NB6,.HzNNNNNNNNNNNNNNNNNNNNNNNNNNNN^ ~ ~  . & $  0   * <( d 0zCopyright 2014 Adobe Systems Incorporated. All rights reserved.FontAwesomeRegularpyrs: FontAwesome: 2012FontAwesome RegularVersion 4.1.0 2013FontAwesomePlease refer to the Copyright section for the font trademark attribution notices.Fort AwesomeDave Gandyhttp://fontawesome.iohttp://fontawesome.io/license/Webfont 1.0Wed May 14 15:41:29 2014zZ      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopq rstuvwxyz{|}~     " !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~uni00A0uni2000uni2001uni2002uni2003uni2004uni2005uni2006uni2007uni2008uni2009uni200Auni202Funi205Funi25FCglassmusicsearchenvelopeheartstar star_emptyuserfilmth_largethth_listokremovezoom_inzoom_outoffsignalcogtrashhomefile_alttimeroad download_altdownloaduploadinbox play_circlerepeatrefreshlist_altlockflag headphones volume_off volume_down volume_upqrcodebarcodetagtagsbookbookmarkprintcamerafontbolditalic text_height text_width align_left align_center align_right align_justifylist indent_left indent_rightfacetime_videopicturepencil map_markeradjusttinteditsharecheckmove step_backward fast_backwardbackwardplaypausestopforward fast_forward step_forwardeject chevron_left chevron_right plus_sign minus_sign remove_signok_sign question_sign info_sign screenshot remove_circle ok_circle ban_circle arrow_left arrow_rightarrow_up arrow_down share_alt resize_full resize_smallexclamation_signgiftleaffireeye_open eye_close warning_signplanecalendarrandomcommentmagnet chevron_up chevron_downretweet shopping_cart folder_close folder_openresize_verticalresize_horizontal bar_chart twitter_sign facebook_sign camera_retrokeycogscomments thumbs_up_altthumbs_down_alt star_half heart_emptysignout linkedin_signpushpin external_linksignintrophy github_sign upload_altlemonphone check_emptybookmark_empty phone_signtwitterfacebookgithubunlock credit_cardrsshddbullhornbell certificate hand_right hand_lefthand_up hand_downcircle_arrow_leftcircle_arrow_rightcircle_arrow_upcircle_arrow_downglobewrenchtasksfilter briefcase fullscreengrouplinkcloudbeakercutcopy paper_clipsave sign_blankreorderulol strikethrough underlinetablemagictruck pinterestpinterest_signgoogle_plus_sign google_plusmoney caret_downcaret_up caret_left caret_rightcolumnssort sort_downsort_up envelope_altlinkedinundolegal dashboard comment_alt comments_altboltsitemapumbrellapaste light_bulbexchangecloud_download cloud_uploaduser_md stethoscopesuitcasebell_altcoffeefood file_text_altbuildinghospital ambulancemedkit fighter_jetbeerh_signf0fedouble_angle_leftdouble_angle_rightdouble_angle_updouble_angle_down angle_left angle_rightangle_up angle_downdesktoplaptoptablet mobile_phone circle_blank quote_left quote_rightspinnercirclereply github_altfolder_close_altfolder_open_alt expand_alt collapse_altsmilefrownmehgamepadkeyboardflag_altflag_checkeredterminalcode reply_allstar_half_emptylocation_arrowcrop code_forkunlink_279 exclamation superscript subscript_283 puzzle_piece microphonemicrophone_offshieldcalendar_emptyfire_extinguisherrocketmaxcdnchevron_sign_leftchevron_sign_rightchevron_sign_upchevron_sign_downhtml5css3anchor unlock_altbullseyeellipsis_horizontalellipsis_vertical_303 play_signticketminus_sign_alt check_minuslevel_up level_down check_sign edit_sign_312 share_signcompasscollapse collapse_top_317eurgbpusdinrjpyrubkrwbtcfile file_textsort_by_alphabet_329sort_by_attributessort_by_attributes_alt sort_by_ordersort_by_order_alt_334_335 youtube_signyoutubexing xing_sign youtube_playdropbox stackexchange instagramflickradnf171bitbucket_signtumblr tumblr_signlong_arrow_down long_arrow_uplong_arrow_leftlong_arrow_rightwindowsandroidlinuxdribbleskype foursquaretrellofemalemalegittipsun_366archivebugvkweiborenren_372stack_exchange_374arrow_circle_alt_left_376dot_circle_alt_378 vimeo_square_380 plus_square_o_382_383_384_385_386_387_388_389uniF1A0f1a1_392_393f1a4_395_396_397_398_399_400f1ab_402_403_404uniF1B1_406_407_408_409_410_411_412_413_414_415_416_417_418_419uniF1C0uniF1C1_422_423_424_425_426_427_428_429_430_431_432_433_434uniF1D0uniF1D1uniF1D2_438_439uniF1D5uniF1D6uniF1D7_443_444_445_446_447_448_449uniF1E0_451_452_453_454_455_456_457_458_459_460_461_462_463_464_466_467_468_469_470_471_472_473_474_475_476_477_478_479KPXYF+X!YKRX!Y+\XY+Ssukui-panel-3.0.6.4/plugin-calendar/lunarcalendarwidget/lunarcalendarmonthitem.h0000644000175000017500000001737714203402514026363 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #ifdef quc #if (QT_VERSION < QT_VERSION_CHECK(5,7,0)) #include #else #include #endif class QDESIGNER_WIDGET_EXPORT LunarCalendarItem : public QWidget #else class LunarCalendarMonthItem : public QWidget #endif { Q_OBJECT Q_ENUMS(DayType) Q_ENUMS(SelectType) Q_PROPERTY(bool select READ getSelect WRITE setSelect) Q_PROPERTY(bool showLunar READ getShowLunar WRITE setShowLunar) Q_PROPERTY(QString bgImage READ getBgImage WRITE setBgImage) Q_PROPERTY(SelectType selectType READ getSelectType WRITE setSelectType) Q_PROPERTY(QDate date READ getDate WRITE setDate) Q_PROPERTY(QString lunar READ getLunar WRITE setLunar) Q_PROPERTY(DayType dayType READ getDayType WRITE setDayType) Q_PROPERTY(QColor borderColor READ getBorderColor WRITE setBorderColor) Q_PROPERTY(QColor weekColor READ getWeekColor WRITE setWeekColor) Q_PROPERTY(QColor superColor READ getSuperColor WRITE setSuperColor) Q_PROPERTY(QColor lunarColor READ getLunarColor WRITE setLunarColor) Q_PROPERTY(QColor currentTextColor READ getCurrentTextColor WRITE setCurrentTextColor) Q_PROPERTY(QColor otherTextColor READ getOtherTextColor WRITE setOtherTextColor) Q_PROPERTY(QColor selectTextColor READ getSelectTextColor WRITE setSelectTextColor) Q_PROPERTY(QColor hoverTextColor READ getHoverTextColor WRITE setHoverTextColor) Q_PROPERTY(QColor currentLunarColor READ getCurrentLunarColor WRITE setCurrentLunarColor) Q_PROPERTY(QColor otherLunarColor READ getOtherLunarColor WRITE setOtherLunarColor) public: enum DayType { DayType_MonthPre = 0, //上月剩余天数 DayType_MonthNext = 1, //下个月的天数 DayType_MonthCurrent = 2, //当月天数 DayType_WeekEnd = 3 //周末 }; enum SelectType { SelectType_Rect = 0, //矩形背景 SelectType_Circle = 1, //圆形背景 SelectType_Triangle = 2, //带三角标 SelectType_Image = 3 //图片背景 }; explicit LunarCalendarMonthItem(QWidget *parent = 0); QMap> worktime; protected: void enterEvent(QEvent *); void leaveEvent(QEvent *); void mousePressEvent(QMouseEvent *); void mouseReleaseEvent(QMouseEvent *); void paintEvent(QPaintEvent *); void drawBg(QPainter *painter); void drawBgCurrent(QPainter *painter, const QColor &color); void drawBgHover(QPainter *painter, const QColor &color); void drawMonth(QPainter *painter); private: bool hover; //鼠标是否悬停 bool pressed; //鼠标是否按下 bool select; //是否选中 bool showLunar; //显示农历 QString bgImage; //背景图片 SelectType selectType; //选中模式 QDate date; //当前日期 QString lunar; //农历信息 DayType dayType; //当前日类型 QColor borderColor; //边框颜色 QColor weekColor; //周末颜色 QColor superColor; //角标颜色 QColor lunarColor; //农历节日颜色 QColor currentTextColor; //当前月文字颜色 QColor otherTextColor; //其他月文字颜色 QColor selectTextColor; //选中日期文字颜色 QColor hoverTextColor; //悬停日期文字颜色 QColor currentLunarColor; //当前月农历文字颜色 QColor otherLunarColor; //其他月农历文字颜色 QColor selectLunarColor; //选中日期农历文字颜色 QColor hoverLunarColor; //悬停日期农历文字颜色 QColor currentBgColor; //当前月背景颜色 QColor otherBgColor; //其他月背景颜色 QColor selectBgColor; //选中日期背景颜色 QColor hoverBgColor; //悬停日期背景颜色 public: bool getSelect() const; bool getShowLunar() const; QString getBgImage() const; SelectType getSelectType() const; QDate getDate() const; QString getLunar() const; DayType getDayType() const; QColor getBorderColor() const; QColor getWeekColor() const; QColor getSuperColor() const; QColor getLunarColor() const; QColor getCurrentTextColor() const; QColor getOtherTextColor() const; QColor getSelectTextColor() const; QColor getHoverTextColor() const; QColor getCurrentLunarColor() const; QColor getOtherLunarColor() const; QColor getSelectLunarColor() const; QColor getHoverLunarColor() const; QColor getCurrentBgColor() const; QColor getOtherBgColor() const; QColor getSelectBgColor() const; QColor getHoverBgColor() const; QSize sizeHint() const; QSize minimumSizeHint() const; public Q_SLOTS: //设置是否选中 void setSelect(bool select); //设置是否显示农历信息 void setShowLunar(bool showLunar); //设置背景图片 void setBgImage(const QString &bgImage); //设置选中背景样式 void setSelectType(const SelectType &selectType); //设置日期 void setDate(const QDate &date); //设置农历 void setLunar(const QString &lunar); //设置类型 void setDayType(const DayType &dayType); //设置日期/农历/类型 void setDate(const QDate &date, const QString &lunar, const DayType &dayType); //设置边框颜色 void setBorderColor(const QColor &borderColor); //设置周末颜色 void setWeekColor(const QColor &weekColor); //设置角标颜色 void setSuperColor(const QColor &superColor); //设置农历节日颜色 void setLunarColor(const QColor &lunarColor); //设置当前月文字颜色 void setCurrentTextColor(const QColor ¤tTextColor); //设置其他月文字颜色 void setOtherTextColor(const QColor &otherTextColor); //设置选中日期文字颜色 void setSelectTextColor(const QColor &selectTextColor); //设置悬停日期文字颜色 void setHoverTextColor(const QColor &hoverTextColor); //设置当前月农历文字颜色 void setCurrentLunarColor(const QColor ¤tLunarColor); //设置其他月农历文字颜色 void setOtherLunarColor(const QColor &otherLunarColor); Q_SIGNALS: void clicked(const QDate &date, const LunarCalendarMonthItem::DayType &dayType); void monthMessage(const QDate &date, const LunarCalendarMonthItem::DayType &dayType); }; #endif // LUNARCALENDARMONTHITEM_H ukui-panel-3.0.6.4/plugin-calendar/lunarcalendarwidget/ui_frmlunarcalendarwidget.h0000644000175000017500000001735214203402514027035 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include #include #include #include #include #include "lunarcalendarwidget.h" QT_BEGIN_NAMESPACE class Ui_frmLunarCalendarWidget { public: QVBoxLayout *verticalLayout; LunarCalendarWidget *lunarCalendarWidget; QWidget *widgetBottom; QHBoxLayout *horizontalLayout; // QLabel *labCalendarStyle; // QComboBox *cboxCalendarStyle; // QLabel *labSelectType; // QComboBox *cboxSelectType; // QLabel *labWeekNameFormat; // QComboBox *cboxWeekNameFormat; // QCheckBox *ckShowLunar; QSpacerItem *horizontalSpacer; void setupUi(QWidget *frmLunarCalendarWidget) { if (frmLunarCalendarWidget->objectName().isEmpty()) frmLunarCalendarWidget->setObjectName(QString::fromUtf8("frmLunarCalendarWidget")); frmLunarCalendarWidget->resize(600, 500); verticalLayout = new QVBoxLayout(frmLunarCalendarWidget); verticalLayout->setObjectName(QString::fromUtf8("verticalLayout")); lunarCalendarWidget = new LunarCalendarWidget(frmLunarCalendarWidget); lunarCalendarWidget->setObjectName(QString::fromUtf8("lunarCalendarWidget")); QSizePolicy sizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding); sizePolicy.setHorizontalStretch(0); sizePolicy.setVerticalStretch(0); sizePolicy.setHeightForWidth(lunarCalendarWidget->sizePolicy().hasHeightForWidth()); lunarCalendarWidget->setSizePolicy(sizePolicy); verticalLayout->addWidget(lunarCalendarWidget); widgetBottom = new QWidget(frmLunarCalendarWidget); widgetBottom->setObjectName(QString::fromUtf8("widgetBottom")); horizontalLayout = new QHBoxLayout(widgetBottom); horizontalLayout->setObjectName(QString::fromUtf8("horizontalLayout")); horizontalLayout->setContentsMargins(0, 0, 0, 0); // labCalendarStyle = new QLabel(widgetBottom); // labCalendarStyle->setObjectName(QString::fromUtf8("labCalendarStyle")); // horizontalLayout->addWidget(labCalendarStyle); // cboxCalendarStyle = new QComboBox(widgetBottom); // cboxCalendarStyle->addItem(QString()); // cboxCalendarStyle->setObjectName(QString::fromUtf8("cboxCalendarStyle")); // cboxCalendarStyle->setMinimumSize(QSize(90, 0)); // horizontalLayout->addWidget(cboxCalendarStyle); // labSelectType = new QLabel(widgetBottom); // labSelectType->setObjectName(QString::fromUtf8("labSelectType")); // horizontalLayout->addWidget(labSelectType); // cboxSelectType = new QComboBox(widgetBottom); // cboxSelectType->addItem(QString()); // cboxSelectType->addItem(QString()); // cboxSelectType->addItem(QString()); // cboxSelectType->addItem(QString()); // cboxSelectType->setObjectName(QString::fromUtf8("cboxSelectType")); // cboxSelectType->setMinimumSize(QSize(90, 0)); // horizontalLayout->addWidget(cboxSelectType); // labWeekNameFormat = new QLabel(widgetBottom); // labWeekNameFormat->setObjectName(QString::fromUtf8("labWeekNameFormat")); // horizontalLayout->addWidget(labWeekNameFormat); // cboxWeekNameFormat = new QComboBox(widgetBottom); // cboxWeekNameFormat->addItem(QString()); // cboxWeekNameFormat->addItem(QString()); // cboxWeekNameFormat->addItem(QString()); // cboxWeekNameFormat->addItem(QString()); // cboxWeekNameFormat->setObjectName(QString::fromUtf8("cboxWeekNameFormat")); // cboxWeekNameFormat->setMinimumSize(QSize(90, 0)); // horizontalLayout->addWidget(cboxWeekNameFormat); // ckShowLunar = new QCheckBox(widgetBottom); // ckShowLunar->setObjectName(QString::fromUtf8("ckShowLunar")); // ckShowLunar->setChecked(true); // horizontalLayout->addWidget(ckShowLunar); horizontalSpacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); horizontalLayout->addItem(horizontalSpacer); // verticalLayout->addWidget(widgetBottom); retranslateUi(frmLunarCalendarWidget); QMetaObject::connectSlotsByName(frmLunarCalendarWidget); } // setupUi void retranslateUi(QWidget *frmLunarCalendarWidget) { frmLunarCalendarWidget->setWindowTitle(QApplication::translate("frmLunarCalendarWidget", "Form", nullptr)); // labCalendarStyle->setText(QApplication::translate("frmLunarCalendarWidget", "\346\225\264\344\275\223\346\240\267\345\274\217", nullptr)); // cboxCalendarStyle->setItemText(0, QApplication::translate("frmLunarCalendarWidget", "\347\272\242\350\211\262\351\243\216\346\240\274", nullptr)); // labSelectType->setText(QApplication::translate("frmLunarCalendarWidget", "\351\200\211\344\270\255\346\240\267\345\274\217", nullptr)); // cboxSelectType->setItemText(0, QApplication::translate("frmLunarCalendarWidget", "\347\237\251\345\275\242\350\203\214\346\231\257", nullptr)); // cboxSelectType->setItemText(1, QApplication::translate("frmLunarCalendarWidget", "\345\234\206\345\275\242\350\203\214\346\231\257", nullptr)); // cboxSelectType->setItemText(2, QApplication::translate("frmLunarCalendarWidget", "\350\247\222\346\240\207\350\203\214\346\231\257", nullptr)); // cboxSelectType->setItemText(3, QApplication::translate("frmLunarCalendarWidget", "\345\233\276\347\211\207\350\203\214\346\231\257", nullptr)); // labWeekNameFormat->setText(QApplication::translate("frmLunarCalendarWidget", "\346\230\237\346\234\237\346\240\274\345\274\217", nullptr)); // cboxWeekNameFormat->setItemText(0, QApplication::translate("frmLunarCalendarWidget", "\347\237\255\345\220\215\347\247\260", nullptr)); // cboxWeekNameFormat->setItemText(1, QApplication::translate("frmLunarCalendarWidget", "\346\231\256\351\200\232\345\220\215\347\247\260", nullptr)); // cboxWeekNameFormat->setItemText(2, QApplication::translate("frmLunarCalendarWidget", "\351\225\277\345\220\215\347\247\260", nullptr)); // cboxWeekNameFormat->setItemText(3, QApplication::translate("frmLunarCalendarWidget", "\350\213\261\346\226\207\345\220\215\347\247\260", nullptr)); // ckShowLunar->setText(QApplication::translate("frmLunarCalendarWidget", "\346\230\276\347\244\272\345\206\234\345\216\206", nullptr)); } // retranslateUi }; namespace Ui { class frmLunarCalendarWidget: public Ui_frmLunarCalendarWidget {}; } // namespace Ui QT_END_NAMESPACE #endif // UI_FRMLUNARCALENDARWIDGET_H ukui-panel-3.0.6.4/plugin-calendar/lunarcalendarwidget/lunarcalendarinfo.h0000644000175000017500000000701514204636772025316 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #ifdef quc #if (QT_VERSION < QT_VERSION_CHECK(5,7,0)) #include #else #include #endif class QDESIGNER_WIDGET_EXPORT LunarCalendarInfo : public QObject #else class LunarCalendarInfo : public QObject #endif { Q_OBJECT public: static LunarCalendarInfo *Instance(); explicit LunarCalendarInfo(QObject *parent = 0); //计算是否闰年 bool isLoopYear(int year); //计算指定年月该月共多少天 int getMonthDays(int year, int month); //计算指定年月对应到该月共多少天 int getTotalMonthDays(int year, int month); //计算指定年月对应星期几 int getFirstDayOfWeek(int year, int month, bool FirstDayisSun); //计算国际节日 QString getHoliday(int month, int day); //计算二十四节气 QString getSolarTerms(int year, int month, int day); //计算农历节日(必须传入农历年份月份) QString getLunarFestival(int month, int day); //计算农历年 天干+地支+生肖 QString getLunarYear(int year); //计算指定年月日农历信息,包括公历节日和农历节日及二十四节气 void getLunarCalendarInfo(int year, int month, int day, QString &strHoliday, QString &strSolarTerms, QString &strLunarFestival, QString &strLunarYear, QString &strLunarMonth, QString &strLunarDay); //获取指定年月日农历信息 QString getLunarInfo(int year, int month, int day, bool yearInfo, bool monthInfo, bool dayInfo); QString getLunarYearMonthDay(int year, int month, int day); QString getLunarMonthDay(int year, int month, int day); QString getLunarDay(int year, int month, int day); private: static QScopedPointer self; QList lunarCalendarTable; //农历年表 QList springFestival; //春节公历日期 QList lunarData; //农历每月数据 QList chineseTwentyFourData; //农历二十四节气数据 QList monthAdd; //公历每月前面的天数 QList listDayName; //农历日期名称集合 QList listMonthName; //农历月份名称集合 QList listSolarTerm; //二十四节气名称集合 QList listTianGan; //天干名称集合 QList listDiZhi; //地支名称集合 QList listShuXiang; //属相名称集合 }; #endif // LUNARCALENDARINFO_H ukui-panel-3.0.6.4/plugin-calendar/lunarcalendarwidget/main.qrc0000644000175000017500000000023514203402514023066 0ustar fengfeng image/bg_calendar.png image/fontawesome-webfont.ttf ukui-panel-3.0.6.4/plugin-calendar/lunarcalendarwidget/lunarcalendarwidget.pro0000644000175000017500000000203514203402514026174 0ustar fengfeng#------------------------------------------------- # # Project created by QtCreator 2017-01-05T22:11:54 # #------------------------------------------------- QT += core gui greaterThan(QT_MAJOR_VERSION, 4): QT += widgets TARGET = lunarcalendarwidget TEMPLATE = app QMAKE_CXXFLAGS += -std=c++11 MOC_DIR = temp/moc RCC_DIR = temp/rcc UI_DIR = temp/ui OBJECTS_DIR = temp/obj DESTDIR = $$PWD/../bin CONFIG += qt warn_off RESOURCES += main.qrc CONFIG += \ link_pkgconfig \ PKGCONFIG += gsettings-qt SOURCES += main.cpp SOURCES += frmlunarcalendarwidget.cpp SOURCES += lunarcalendaritem.cpp SOURCES += lunarcalendarinfo.cpp SOURCES += lunarcalendarwidget.cpp HEADERS += frmlunarcalendarwidget.h HEADERS += lunarcalendaritem.h HEADERS += lunarcalendarinfo.h HEADERS += lunarcalendarwidget.h FORMS += frmlunarcalendarwidget.ui INCLUDEPATH += $$PWD ukui-panel-3.0.6.4/plugin-calendar/lunarcalendarwidget/lunarcalendarmonthitem.cpp0000644000175000017500000003066314203402514026707 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see LunarCalendarMonthItem::LunarCalendarMonthItem(QWidget *parent) : QWidget(parent) { hover = false; pressed = false; select = false; select = false; showLunar = true; bgImage = ":/image/bg_calendar.png"; selectType = SelectType_Rect; date = QDate::currentDate(); lunar = "初一"; dayType = DayType_MonthCurrent; //实时监听主题变化 const QByteArray id("org.ukui.style"); QGSettings * fontSetting = new QGSettings(id, QByteArray(), this); connect(fontSetting, &QGSettings::changed,[=](QString key) { if(fontSetting->get("style-name").toString() == "ukui-default") { weekColor = QColor(255, 255, 255); currentTextColor = QColor(255, 255, 255); otherTextColor = QColor(255, 255, 255,40); otherLunarColor = QColor(255, 255, 255,40); currentLunarColor = QColor(255, 255, 255,90); lunarColor = QColor(255, 255, 255,90); } else if(fontSetting->get("style-name").toString() == "ukui-light") { weekColor = QColor(0, 0, 0); currentTextColor = QColor(0, 0, 0); otherTextColor = QColor(0,0,0,40); otherLunarColor = QColor(0,0,0,40); currentLunarColor = QColor(0,0,0,90); lunarColor = QColor(0,0,0,90); } else if(fontSetting->get("style-name").toString() == "ukui-dark") { weekColor = QColor(255, 255, 255); currentTextColor = QColor(255, 255, 255); otherTextColor = QColor(255, 255, 255,40); otherLunarColor = QColor(255, 255, 255,40); currentLunarColor = QColor(255, 255, 255,90); lunarColor = QColor(255, 255, 255,90); } }); if(fontSetting->get("style-name").toString() == "ukui-light") { weekColor = QColor(0, 0, 0); currentTextColor = QColor(0, 0, 0); otherTextColor = QColor(0,0,0,40); otherLunarColor = QColor(0,0,0,40); currentLunarColor = QColor(0,0,0,90); lunarColor = QColor(0,0,0,90); } else { weekColor = QColor(255, 255, 255); currentTextColor = QColor(255, 255, 255); otherTextColor = QColor(255, 255, 255,40); otherLunarColor = QColor(255, 255, 255,40); currentLunarColor = QColor(255, 255, 255,90); lunarColor = QColor(255, 255, 255,90); } borderColor = QColor(180, 180, 180); superColor = QColor(255, 129, 6); selectTextColor = QColor(255, 255, 255); hoverTextColor = QColor(250, 250, 250); selectLunarColor = QColor(255, 255, 255); hoverLunarColor = QColor(250, 250, 250); currentBgColor = QColor(255, 255, 255); otherBgColor = QColor(240, 240, 240); selectBgColor = QColor(55,143,250); hoverBgColor = QColor(204, 183, 180); } void LunarCalendarMonthItem::enterEvent(QEvent *) { hover = true; this->update(); } void LunarCalendarMonthItem::leaveEvent(QEvent *) { hover = false; this->update(); } void LunarCalendarMonthItem::mousePressEvent(QMouseEvent *) { pressed = true; this->update(); // Q_EMIT clicked(date, dayType); Q_EMIT monthMessage(date, dayType); } void LunarCalendarMonthItem::mouseReleaseEvent(QMouseEvent *) { pressed = false; this->update(); } void LunarCalendarMonthItem::paintEvent(QPaintEvent *) { QDate dateNow = QDate::currentDate(); //绘制准备工作,启用反锯齿 QPainter painter(this); painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing); //绘制背景和边框 drawBg(&painter); //对比当前的时间,画选中状态 if(dateNow.month() == date.month() && dateNow.year() == date.year()) { drawBgCurrent(&painter, selectBgColor); } //绘制悬停状态 if (hover) { drawBgHover(&painter, hoverBgColor); } //绘制选中状态 if (select) { drawBgHover(&painter, hoverBgColor); } //绘制日期 drawMonth(&painter); } void LunarCalendarMonthItem::drawBg(QPainter *painter) { painter->save(); //根据当前类型选择对应的颜色 QColor bgColor = currentBgColor; if (dayType == DayType_MonthPre || dayType == DayType_MonthNext) { bgColor = otherBgColor; } painter->restore(); } void LunarCalendarMonthItem::drawBgCurrent(QPainter *painter, const QColor &color) { painter->save(); painter->setPen(Qt::NoPen); painter->setBrush(color); QRect rect = this->rect(); painter->drawRoundedRect(rect,4,4); painter->restore(); } void LunarCalendarMonthItem::drawBgHover(QPainter *painter, const QColor &color) { painter->save(); QRect rect = this->rect(); painter->setPen(QPen(QColor(55,143,250),2)); painter->drawRoundedRect(rect,4,4); painter->restore(); } void LunarCalendarMonthItem::drawMonth(QPainter *painter) { int width = this->width(); int height = this->height(); int side = qMin(width, height); painter->save(); //根据当前类型选择对应的颜色 QColor color = currentTextColor; if (dayType == DayType_MonthPre || dayType == DayType_MonthNext) { color = otherTextColor; } else if (dayType == DayType_WeekEnd) { color = weekColor; } painter->setPen(color); QFont font; font.setPixelSize(side * 0.2); //设置文字粗细 font.setBold(true); painter->setFont(font); QRect dayRect = QRect(0, 0, width, height / 1.7); QString arg = QString::number(date.month()) /*+ "月"*/; painter->drawText(dayRect, Qt::AlignHCenter | Qt::AlignBottom, arg); painter->restore(); } bool LunarCalendarMonthItem::getSelect() const { return this->select; } bool LunarCalendarMonthItem::getShowLunar() const { return this->showLunar; } QString LunarCalendarMonthItem::getBgImage() const { return this->bgImage; } LunarCalendarMonthItem::SelectType LunarCalendarMonthItem::getSelectType() const { return this->selectType; } QDate LunarCalendarMonthItem::getDate() const { return this->date; } QString LunarCalendarMonthItem::getLunar() const { return this->lunar; } LunarCalendarMonthItem::DayType LunarCalendarMonthItem::getDayType() const { return this->dayType; } QColor LunarCalendarMonthItem::getBorderColor() const { return this->borderColor; } QColor LunarCalendarMonthItem::getWeekColor() const { return this->weekColor; } QColor LunarCalendarMonthItem::getSuperColor() const { return this->superColor; } QColor LunarCalendarMonthItem::getLunarColor() const { return this->lunarColor; } QColor LunarCalendarMonthItem::getCurrentTextColor() const { return this->currentTextColor; } QColor LunarCalendarMonthItem::getOtherTextColor() const { return this->otherTextColor; } QColor LunarCalendarMonthItem::getSelectTextColor() const { return this->selectTextColor; } QColor LunarCalendarMonthItem::getHoverTextColor() const { return this->hoverTextColor; } QColor LunarCalendarMonthItem::getCurrentLunarColor() const { return this->currentLunarColor; } QColor LunarCalendarMonthItem::getOtherLunarColor() const { return this->otherLunarColor; } QColor LunarCalendarMonthItem::getSelectLunarColor() const { return this->selectLunarColor; } QColor LunarCalendarMonthItem::getHoverLunarColor() const { return this->hoverLunarColor; } QColor LunarCalendarMonthItem::getCurrentBgColor() const { return this->currentBgColor; } QColor LunarCalendarMonthItem::getOtherBgColor() const { return this->otherBgColor; } QColor LunarCalendarMonthItem::getSelectBgColor() const { return this->selectBgColor; } QColor LunarCalendarMonthItem::getHoverBgColor() const { return this->hoverBgColor; } QSize LunarCalendarMonthItem::sizeHint() const { return QSize(100, 100); } QSize LunarCalendarMonthItem::minimumSizeHint() const { return QSize(20, 20); } void LunarCalendarMonthItem::setSelect(bool select) { if (this->select != select) { this->select = select; this->update(); } } void LunarCalendarMonthItem::setShowLunar(bool showLunar) { this->showLunar = showLunar; this->update(); } void LunarCalendarMonthItem::setBgImage(const QString &bgImage) { if (this->bgImage != bgImage) { this->bgImage = bgImage; this->update(); } } void LunarCalendarMonthItem::setSelectType(const LunarCalendarMonthItem::SelectType &selectType) { if (this->selectType != selectType) { this->selectType = selectType; this->update(); } } void LunarCalendarMonthItem::setDate(const QDate &date) { if (this->date != date) { this->date = date; this->update(); } } void LunarCalendarMonthItem::setLunar(const QString &lunar) { if (this->lunar != lunar) { this->lunar = lunar; this->update(); } } void LunarCalendarMonthItem::setDayType(const LunarCalendarMonthItem::DayType &dayType) { if (this->dayType != dayType) { this->dayType = dayType; this->update(); } } void LunarCalendarMonthItem::setDate(const QDate &date, const QString &lunar, const DayType &dayType) { this->date = date; this->lunar = lunar; this->dayType = dayType; this->update(); } void LunarCalendarMonthItem::setBorderColor(const QColor &borderColor) { if (this->borderColor != borderColor) { this->borderColor = borderColor; this->update(); } } void LunarCalendarMonthItem::setWeekColor(const QColor &weekColor) { if (this->weekColor != weekColor) { this->weekColor = weekColor; this->update(); } } void LunarCalendarMonthItem::setSuperColor(const QColor &superColor) { if (this->superColor != superColor) { this->superColor = superColor; this->update(); } } void LunarCalendarMonthItem::setLunarColor(const QColor &lunarColor) { if (this->lunarColor != lunarColor) { this->lunarColor = lunarColor; this->update(); } } void LunarCalendarMonthItem::setCurrentTextColor(const QColor ¤tTextColor) { if (this->currentTextColor != currentTextColor) { this->currentTextColor = currentTextColor; this->update(); } } void LunarCalendarMonthItem::setOtherTextColor(const QColor &otherTextColor) { if (this->otherTextColor != otherTextColor) { this->otherTextColor = otherTextColor; this->update(); } } void LunarCalendarMonthItem::setSelectTextColor(const QColor &selectTextColor) { if (this->selectTextColor != selectTextColor) { this->selectTextColor = selectTextColor; this->update(); } } void LunarCalendarMonthItem::setHoverTextColor(const QColor &hoverTextColor) { if (this->hoverTextColor != hoverTextColor) { this->hoverTextColor = hoverTextColor; this->update(); } } void LunarCalendarMonthItem::setCurrentLunarColor(const QColor ¤tLunarColor) { if (this->currentLunarColor != currentLunarColor) { this->currentLunarColor = currentLunarColor; this->update(); } } void LunarCalendarMonthItem::setOtherLunarColor(const QColor &otherLunarColor) { if (this->otherLunarColor != otherLunarColor) { this->otherLunarColor = otherLunarColor; this->update(); } } ukui-panel-3.0.6.4/plugin-calendar/lunarcalendarwidget/lunarcalendaryearitem.h0000644000175000017500000001736414204636772026212 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #ifdef quc #if (QT_VERSION < QT_VERSION_CHECK(5,7,0)) #include #else #include #endif class QDESIGNER_WIDGET_EXPORT LunarCalendarItem : public QWidget #else class LunarCalendarYearItem : public QWidget #endif { Q_OBJECT Q_ENUMS(DayType) Q_ENUMS(SelectType) Q_PROPERTY(bool select READ getSelect WRITE setSelect) Q_PROPERTY(bool showLunar READ getShowLunar WRITE setShowLunar) Q_PROPERTY(QString bgImage READ getBgImage WRITE setBgImage) Q_PROPERTY(SelectType selectType READ getSelectType WRITE setSelectType) Q_PROPERTY(QDate date READ getDate WRITE setDate) Q_PROPERTY(QString lunar READ getLunar WRITE setLunar) Q_PROPERTY(DayType dayType READ getDayType WRITE setDayType) Q_PROPERTY(QColor borderColor READ getBorderColor WRITE setBorderColor) Q_PROPERTY(QColor weekColor READ getWeekColor WRITE setWeekColor) Q_PROPERTY(QColor superColor READ getSuperColor WRITE setSuperColor) Q_PROPERTY(QColor lunarColor READ getLunarColor WRITE setLunarColor) Q_PROPERTY(QColor currentTextColor READ getCurrentTextColor WRITE setCurrentTextColor) Q_PROPERTY(QColor otherTextColor READ getOtherTextColor WRITE setOtherTextColor) Q_PROPERTY(QColor selectTextColor READ getSelectTextColor WRITE setSelectTextColor) Q_PROPERTY(QColor hoverTextColor READ getHoverTextColor WRITE setHoverTextColor) Q_PROPERTY(QColor currentLunarColor READ getCurrentLunarColor WRITE setCurrentLunarColor) Q_PROPERTY(QColor otherLunarColor READ getOtherLunarColor WRITE setOtherLunarColor) public: enum DayType { DayType_MonthPre = 0, //上月剩余天数 DayType_MonthNext = 1, //下个月的天数 DayType_MonthCurrent = 2, //当月天数 DayType_WeekEnd = 3 //周末 }; enum SelectType { SelectType_Rect = 0, //矩形背景 SelectType_Circle = 1, //圆形背景 SelectType_Triangle = 2, //带三角标 SelectType_Image = 3 //图片背景 }; explicit LunarCalendarYearItem(QWidget *parent = 0); QMap> worktime; protected: void enterEvent(QEvent *); void leaveEvent(QEvent *); void mousePressEvent(QMouseEvent *); void mouseReleaseEvent(QMouseEvent *); void paintEvent(QPaintEvent *); void drawBg(QPainter *painter); void drawBgCurrent(QPainter *painter, const QColor &color); void drawBgHover(QPainter *painter, const QColor &color); void drawYear(QPainter *painter); private: bool hover; //鼠标是否悬停 bool pressed; //鼠标是否按下 bool select; //是否选中 bool showLunar; //显示农历 QString bgImage; //背景图片 SelectType selectType; //选中模式 QDate date; //当前日期 QString lunar; //农历信息 DayType dayType; //当前日类型 QColor borderColor; //边框颜色 QColor weekColor; //周末颜色 QColor superColor; //角标颜色 QColor lunarColor; //农历节日颜色 QColor currentTextColor; //当前月文字颜色 QColor otherTextColor; //其他月文字颜色 QColor selectTextColor; //选中日期文字颜色 QColor hoverTextColor; //悬停日期文字颜色 QColor currentLunarColor; //当前月农历文字颜色 QColor otherLunarColor; //其他月农历文字颜色 QColor selectLunarColor; //选中日期农历文字颜色 QColor hoverLunarColor; //悬停日期农历文字颜色 QColor currentBgColor; //当前月背景颜色 QColor otherBgColor; //其他月背景颜色 QColor selectBgColor; //选中日期背景颜色 QColor hoverBgColor; //悬停日期背景颜色 public: bool getSelect() const; bool getShowLunar() const; QString getBgImage() const; SelectType getSelectType() const; QDate getDate() const; QString getLunar() const; DayType getDayType() const; QColor getBorderColor() const; QColor getWeekColor() const; QColor getSuperColor() const; QColor getLunarColor() const; QColor getCurrentTextColor() const; QColor getOtherTextColor() const; QColor getSelectTextColor() const; QColor getHoverTextColor() const; QColor getCurrentLunarColor() const; QColor getOtherLunarColor() const; QColor getSelectLunarColor() const; QColor getHoverLunarColor() const; QColor getCurrentBgColor() const; QColor getOtherBgColor() const; QColor getSelectBgColor() const; QColor getHoverBgColor() const; QSize sizeHint() const; QSize minimumSizeHint() const; public Q_SLOTS: //设置是否选中 void setSelect(bool select); //设置是否显示农历信息 void setShowLunar(bool showLunar); //设置背景图片 void setBgImage(const QString &bgImage); //设置选中背景样式 void setSelectType(const SelectType &selectType); //设置日期 void setDate(const QDate &date); //设置农历 void setLunar(const QString &lunar); //设置类型 void setDayType(const DayType &dayType); //设置日期/农历/类型 void setDate(const QDate &date, const QString &lunar, const DayType &dayType); //设置边框颜色 void setBorderColor(const QColor &borderColor); //设置周末颜色 void setWeekColor(const QColor &weekColor); //设置角标颜色 void setSuperColor(const QColor &superColor); //设置农历节日颜色 void setLunarColor(const QColor &lunarColor); //设置当前月文字颜色 void setCurrentTextColor(const QColor ¤tTextColor); //设置其他月文字颜色 void setOtherTextColor(const QColor &otherTextColor); //设置选中日期文字颜色 void setSelectTextColor(const QColor &selectTextColor); //设置悬停日期文字颜色 void setHoverTextColor(const QColor &hoverTextColor); //设置当前月农历文字颜色 void setCurrentLunarColor(const QColor ¤tLunarColor); //设置其他月农历文字颜色 void setOtherLunarColor(const QColor &otherLunarColor); Q_SIGNALS: void clicked(const QDate &date, const LunarCalendarYearItem::DayType &dayType); void yearMessage(const QDate &date, const LunarCalendarYearItem::DayType &dayType); }; #endif // LUNARCALENDARITEM_H ukui-panel-3.0.6.4/plugin-calendar/lunarcalendarwidget/lunarcalendarwidget.h0000644000175000017500000003221314203402514025624 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include #include #include "qfontdatabase.h" #include "qdatetime.h" #include "qlayout.h" #include "qlabel.h" #include "qpushbutton.h" #include "qtoolbutton.h" #include "qcombobox.h" #include "qdebug.h" #include #include #include #include "picturetowhite.h" #include #include #include #include #include #include #include "../../panel/pluginsettings.h" #include "../../panel/iukuipanelplugin.h" #include "lunarcalendarinfo.h" #include "lunarcalendaritem.h" #include "lunarcalendaryearitem.h" #include "lunarcalendarmonthitem.h" #include "customstylePushbutton.h" #include #include #include #include #include #include class QLabel; class statelabel; class QComboBox; class LunarCalendarYearItem; class LunarCalendarMonthItem; class LunarCalendarItem; class m_PartLineWidget; #ifdef quc #if (QT_VERSION < QT_VERSION_CHECK(5,7,0)) #include #else #include #endif class QDESIGNER_WIDGET_EXPORT LunarCalendarWidget : public QWidget #else class LunarCalendarWidget : public QWidget #endif { Q_OBJECT Q_ENUMS(CalendarStyle) Q_ENUMS(WeekNameFormat) Q_ENUMS(SelectType) Q_PROPERTY(CalendarStyle calendarStyle READ getCalendarStyle WRITE setCalendarStyle) Q_PROPERTY(QDate date READ getDate WRITE setDate) Q_PROPERTY(QColor weekTextColor READ getWeekTextColor WRITE setWeekTextColor) Q_PROPERTY(QColor weekBgColor READ getWeekBgColor WRITE setWeekBgColor) Q_PROPERTY(bool showLunar READ getShowLunar WRITE setShowLunar) Q_PROPERTY(QString bgImage READ getBgImage WRITE setBgImage) Q_PROPERTY(SelectType selectType READ getSelectType WRITE setSelectType) Q_PROPERTY(QColor borderColor READ getBorderColor WRITE setBorderColor) Q_PROPERTY(QColor weekColor READ getWeekColor WRITE setWeekColor) Q_PROPERTY(QColor superColor READ getSuperColor WRITE setSuperColor) Q_PROPERTY(QColor lunarColor READ getLunarColor WRITE setLunarColor) Q_PROPERTY(QColor currentTextColor READ getCurrentTextColor WRITE setCurrentTextColor) Q_PROPERTY(QColor otherTextColor READ getOtherTextColor WRITE setOtherTextColor) Q_PROPERTY(QColor selectTextColor READ getSelectTextColor WRITE setSelectTextColor) Q_PROPERTY(QColor hoverTextColor READ getHoverTextColor WRITE setHoverTextColor) Q_PROPERTY(QColor currentLunarColor READ getCurrentLunarColor WRITE setCurrentLunarColor) Q_PROPERTY(QColor otherLunarColor READ getOtherLunarColor WRITE setOtherLunarColor) Q_PROPERTY(QColor selectLunarColor READ getSelectLunarColor WRITE setSelectLunarColor) Q_PROPERTY(QColor hoverLunarColor READ getHoverLunarColor WRITE setHoverLunarColor) Q_PROPERTY(QColor currentBgColor READ getCurrentBgColor WRITE setCurrentBgColor) Q_PROPERTY(QColor otherBgColor READ getOtherBgColor WRITE setOtherBgColor) Q_PROPERTY(QColor selectBgColor READ getSelectBgColor WRITE setSelectBgColor) Q_PROPERTY(QColor hoverBgColor READ getHoverBgColor WRITE setHoverBgColor) public: enum CalendarStyle { CalendarStyle_Red = 0 }; enum WeekNameFormat { WeekNameFormat_Short = 0, //短名称 WeekNameFormat_Normal = 1, //普通名称 WeekNameFormat_Long = 2, //长名称 WeekNameFormat_En = 3 //英文名称 }; enum SelectType { SelectType_Rect = 0, //矩形背景 SelectType_Circle = 1, //圆形背景 SelectType_Triangle = 2, //带三角标 SelectType_Image = 3 //图片背景 }; explicit LunarCalendarWidget(QWidget *parent = 0); ~LunarCalendarWidget(); private: QLabel *datelabel; QLabel *timelabel; QLabel *lunarlabel; QTimer *timer; QVBoxLayout *timeShow; QWidget *widgetTime; QPushButton *btnYear; QPushButton *btnMonth; QPushButton *btnToday; QWidget *labWidget; QLabel *labBottom; QHBoxLayout *labLayout; m_PartLineWidget *lineUp; m_PartLineWidget *lineDown; statelabel *btnPrevYear; statelabel *btnNextYear; QLabel *yijichooseLabel; QCheckBox *yijichoose; QVBoxLayout *yijiLayout; QWidget *yijiWidget; QLabel *yiLabel; QLabel *jiLabel; QWidget *widgetWeek; QWidget *widgetDayBody; QWidget *widgetYearBody; QWidget *widgetmonthBody; QProcess *myProcess; QString timemodel = 0; bool yijistate = false; bool lunarstate =false; bool oneRun = true; // IUKUIPanelPlugin *mPlugin; QString dateShowMode; QMap worktimeinside; QMap> worktime; void analysisWorktimeJs(); //解析js文件 void downLabelHandle(const QDate &date); QFont iconFont; //图形字体 bool btnClick; //按钮单击,避开下拉选择重复触发 QComboBox *cboxYearandMonth; //年份下拉框 QLabel *cboxYearandMonthLabel; QList labWeeks; //顶部星期名称 QList dayItems; //日期元素 QList yearItems; //年份元素 QList monthItems; //月份元素 QFont m_font; CalendarStyle calendarStyle; //整体样式 bool FirstdayisSun; //首日期为周日 QDate date; //当前日期 QDate clickDate; //保存点击日期 QColor weekTextColor; //星期名称文字颜色 QColor weekBgColor; //星期名称背景色 bool showLunar; //显示农历 QString bgImage; //背景图片 SelectType selectType; //选中模式 QColor borderColor; //边框颜色 QColor weekColor; //周末颜色 QColor superColor; //角标颜色 QColor lunarColor; //农历节日颜色 QColor currentTextColor; //当前月文字颜色 QColor otherTextColor; //其他月文字颜色 QColor selectTextColor; //选中日期文字颜色 QColor hoverTextColor; //悬停日期文字颜色 QColor currentLunarColor; //当前月农历文字颜色 QColor otherLunarColor; //其他月农历文字颜色 QColor selectLunarColor; //选中日期农历文字颜色 QColor hoverLunarColor; //悬停日期农历文字颜色 QColor currentBgColor; //当前月背景颜色 QColor otherBgColor; //其他月背景颜色 QColor selectBgColor; //选中日期背景颜色 QColor hoverBgColor; //悬停日期背景颜色 QGSettings *calendar_gsettings; void setColor(bool mdark_style); void _timeUpdate(); void yijihandle(const QDate &date); QString getSettings(); void setSettings(QString arg); QGSettings *style_settings; bool dark_style; QStringList getLocale(); void setLocaleCalendar(); protected : void wheelEvent(QWheelEvent *event); private Q_SLOTS: void initWidget(); void initStyle(); void initDate(); void changeDate(const QDate &date); void yearChanged(const QString &arg1); void monthChanged(const QString &arg1); void clicked(const QDate &date, const LunarCalendarItem::DayType &dayType); void dayChanged(const QDate &date,const QDate &m_date); void dateChanged(int year, int month, int day); void timerUpdate(); void customButtonsClicked(int x); void yearWidgetChange(); void monthWidgetChange(); public: CalendarStyle getCalendarStyle() const; QDate getDate() const; QColor getWeekTextColor() const; QColor getWeekBgColor() const; bool getShowLunar() const; QString getBgImage() const; SelectType getSelectType() const; QColor getBorderColor() const; QColor getWeekColor() const; QColor getSuperColor() const; QColor getLunarColor() const; QColor getCurrentTextColor() const; QColor getOtherTextColor() const; QColor getSelectTextColor() const; QColor getHoverTextColor() const; QColor getCurrentLunarColor() const; QColor getOtherLunarColor() const; QColor getSelectLunarColor() const; QColor getHoverLunarColor() const; QColor getCurrentBgColor() const; QColor getOtherBgColor() const; QColor getSelectBgColor() const; QColor getHoverBgColor() const; QSize sizeHint() const; QSize minimumSizeHint() const; QString locale ; public Q_SLOTS: void updateYearClicked(const QDate &date, const LunarCalendarYearItem::DayType &dayType); void updateMonthClicked(const QDate &date, const LunarCalendarMonthItem::DayType &dayType); //上一年,下一年 void showPreviousYear(); void showNextYear(); //上一月,下一月 void showPreviousMonth(bool date_clicked = true); void showNextMonth(bool date_clicked = true); //转到今天 void showToday(); //设置整体样式 void setCalendarStyle(const CalendarStyle &calendarStyle); //设置星期名称格式 void setWeekNameFormat(bool FirstDayisSun); //设置日期 void setDate(const QDate &date); //设置顶部星期名称文字颜色+背景色 void setWeekTextColor(const QColor &weekTextColor); void setWeekBgColor(const QColor &weekBgColor); //设置是否显示农历信息 void setShowLunar(bool showLunar); //设置背景图片 void setBgImage(const QString &bgImage); //设置选中背景样式 void setSelectType(const SelectType &selectType); //设置边框颜色 void setBorderColor(const QColor &borderColor); //设置周末颜色 void setWeekColor(const QColor &weekColor); //设置角标颜色 void setSuperColor(const QColor &superColor); //设置农历节日颜色 void setLunarColor(const QColor &lunarColor); //设置当前月文字颜色 void setCurrentTextColor(const QColor ¤tTextColor); //设置其他月文字颜色 void setOtherTextColor(const QColor &otherTextColor); //设置选中日期文字颜色 void setSelectTextColor(const QColor &selectTextColor); //设置悬停日期文字颜色 void setHoverTextColor(const QColor &hoverTextColor); //设置当前月农历文字颜色 void setCurrentLunarColor(const QColor ¤tLunarColor); //设置其他月农历文字颜色 void setOtherLunarColor(const QColor &otherLunarColor); //设置选中日期农历文字颜色 void setSelectLunarColor(const QColor &selectLunarColor); //设置悬停日期农历文字颜色 void setHoverLunarColor(const QColor &hoverLunarColor); //设置当前月背景颜色 void setCurrentBgColor(const QColor ¤tBgColor); //设置其他月背景颜色 void setOtherBgColor(const QColor &otherBgColor); //设置选中日期背景颜色 void setSelectBgColor(const QColor &selectBgColor); //设置悬停日期背景颜色 void setHoverBgColor(const QColor &hoverBgColor); Q_SIGNALS: void clicked(const QDate &date); void selectionChanged(); void yijiChangeUp(); void yijiChangeDown(); }; class m_PartLineWidget : public QWidget { Q_OBJECT public: explicit m_PartLineWidget(QWidget *parent = nullptr); void paintEvent(QPaintEvent *event); }; class statelabel : public QLabel { Q_OBJECT public: statelabel(); protected: void mousePressEvent(QMouseEvent *event); Q_SIGNALS : void labelclick(); }; #endif // LUNARCALENDARWIDGET_H ukui-panel-3.0.6.4/plugin-calendar/lunarcalendarwidget/lunarcalendarinfo.cpp0000644000175000017500000011737314204636772025662 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #define year_2099 QScopedPointer LunarCalendarInfo::self; LunarCalendarInfo *LunarCalendarInfo::Instance() { if (self.isNull()) { static QMutex mutex; QMutexLocker locker(&mutex); if (self.isNull()) { self.reset(new LunarCalendarInfo); } } return self.data(); } LunarCalendarInfo::LunarCalendarInfo(QObject *parent) : QObject(parent) { //农历查表 lunarCalendarTable << 0x04AE53 << 0x0A5748 << 0x5526BD << 0x0D2650 << 0x0D9544 << 0x46AAB9 << 0x056A4D << 0x09AD42 << 0x24AEB6 << 0x04AE4A; //1901-1910 lunarCalendarTable << 0x6A4DBE << 0x0A4D52 << 0x0D2546 << 0x5D52BA << 0x0B544E << 0x0D6A43 << 0x296D37 << 0x095B4B << 0x749BC1 << 0x049754; //1911-1920 lunarCalendarTable << 0x0A4B48 << 0x5B25BC << 0x06A550 << 0x06D445 << 0x4ADAB8 << 0x02B64D << 0x095742 << 0x2497B7 << 0x04974A << 0x664B3E; //1921-1930 lunarCalendarTable << 0x0D4A51 << 0x0EA546 << 0x56D4BA << 0x05AD4E << 0x02B644 << 0x393738 << 0x092E4B << 0x7C96BF << 0x0C9553 << 0x0D4A48; //1931-1940 lunarCalendarTable << 0x6DA53B << 0x0B554F << 0x056A45 << 0x4AADB9 << 0x025D4D << 0x092D42 << 0x2C95B6 << 0x0A954A << 0x7B4ABD << 0x06CA51; //1941-1950 lunarCalendarTable << 0x0B5546 << 0x555ABB << 0x04DA4E << 0x0A5B43 << 0x352BB8 << 0x052B4C << 0x8A953F << 0x0E9552 << 0x06AA48 << 0x6AD53C; //1951-1960 lunarCalendarTable << 0x0AB54F << 0x04B645 << 0x4A5739 << 0x0A574D << 0x052642 << 0x3E9335 << 0x0D9549 << 0x75AABE << 0x056A51 << 0x096D46; //1961-1970 lunarCalendarTable << 0x54AEBB << 0x04AD4F << 0x0A4D43 << 0x4D26B7 << 0x0D254B << 0x8D52BF << 0x0B5452 << 0x0B6A47 << 0x696D3C << 0x095B50; //1971-1980 lunarCalendarTable << 0x049B45 << 0x4A4BB9 << 0x0A4B4D << 0xAB25C2 << 0x06A554 << 0x06D449 << 0x6ADA3D << 0x0AB651 << 0x093746 << 0x5497BB; //1981-1990 lunarCalendarTable << 0x04974F << 0x064B44 << 0x36A537 << 0x0EA54A << 0x86B2BF << 0x05AC53 << 0x0AB647 << 0x5936BC << 0x092E50 << 0x0C9645; //1991-2000 lunarCalendarTable << 0x4D4AB8 << 0x0D4A4C << 0x0DA541 << 0x25AAB6 << 0x056A49 << 0x7AADBD << 0x025D52 << 0x092D47 << 0x5C95BA << 0x0A954E; //2001-2010 lunarCalendarTable << 0x0B4A43 << 0x4B5537 << 0x0AD54A << 0x955ABF << 0x04BA53 << 0x0A5B48 << 0x652BBC << 0x052B50 << 0x0A9345 << 0x474AB9; //2011-2020 lunarCalendarTable << 0x06AA4C << 0x0AD541 << 0x24DAB6 << 0x04B64A << 0x69573D << 0x0A4E51 << 0x0D2646 << 0x5E933A << 0x0D534D << 0x05AA43; //2021-2030 lunarCalendarTable << 0x36B537 << 0x096D4B << 0xB4AEBF << 0x04AD53 << 0x0A4D48 << 0x6D25BC << 0x0D254F << 0x0D5244 << 0x5DAA38 << 0x0B5A4C; //2031-2040 lunarCalendarTable << 0x056D41 << 0x24ADB6 << 0x049B4A << 0x7A4BBE << 0x0A4B51 << 0x0AA546 << 0x5B52BA << 0x06D24E << 0x0ADA42 << 0x355B37; //2041-2050 lunarCalendarTable << 0x09374B << 0x8497C1 << 0x049753 << 0x064B48 << 0x66A53C << 0x0EA54F << 0x06B244 << 0x4AB638 << 0x0AAE4C << 0x092E42; //2051-2060 lunarCalendarTable << 0x3C9735 << 0x0C9649 << 0x7D4ABD << 0x0D4A51 << 0x0DA545 << 0x55AABA << 0x056A4E << 0x0A6D43 << 0x452EB7 << 0x052D4B; //2061-2070 lunarCalendarTable << 0x8A95BF << 0x0A9553 << 0x0B4A47 << 0x6B553B << 0x0AD54F << 0x055A45 << 0x4A5D38 << 0x0A5B4C << 0x052B42 << 0x3A93B6; //2071-2080 lunarCalendarTable << 0x069349 << 0x7729BD << 0x06AA51 << 0x0AD546 << 0x54DABA << 0x04B64E << 0x0A5743 << 0x452738 << 0x0D264A << 0x8E933E; //2081-2090 lunarCalendarTable << 0x0D5252 << 0x0DAA47 << 0x66B53B << 0x056D4F << 0x04AE45 << 0x4A4EB9 << 0x0A4D4C << 0x0D1541 << 0x2D92B5; //2091-2099 //每年春节对应的公历日期 springFestival << 130 << 217 << 206; // 1968 1969 1970 springFestival << 127 << 215 << 203 << 123 << 211 << 131 << 218 << 207 << 128 << 216; // 1971--1980 springFestival << 205 << 125 << 213 << 202 << 220 << 209 << 219 << 217 << 206 << 127; // 1981--1990 springFestival << 215 << 204 << 123 << 210 << 131 << 219 << 207 << 128 << 216 << 205; // 1991--2000 springFestival << 124 << 212 << 201 << 122 << 209 << 129 << 218 << 207 << 126 << 214; // 2001--2010 springFestival << 203 << 123 << 210 << 131 << 219 << 208 << 128 << 216 << 205 << 125; // 2011--2020 springFestival << 212 << 201 << 122 << 210 << 129 << 217 << 206 << 126 << 213 << 203; // 2021--2030 springFestival << 123 << 211 << 131 << 219 << 208 << 128 << 215 << 204 << 124 << 212; // 2031--2040 //16--18位表示闰几月 0--12位表示农历每月的数据 高位表示1月 低位表示12月(农历闰月就会多一个月) lunarData << 461653 << 1386 << 2413; // 1968 1969 1970 lunarData << 330077 << 1197 << 2637 << 268877 << 3365 << 531109 << 2900 << 2922 << 398042 << 2395; // 1971--1980 lunarData << 1179 << 267415 << 2635 << 661067 << 1701 << 1748 << 398772 << 2742 << 2391 << 330031; // 1981--1990 lunarData << 1175 << 1611 << 200010 << 3749 << 527717 << 1452 << 2742 << 332397 << 2350 << 3222; // 1991--2000 lunarData << 268949 << 3402 << 3493 << 133973 << 1386 << 464219 << 605 << 2349 << 334123 << 2709; // 2001--2010 lunarData << 2890 << 267946 << 2773 << 592565 << 1210 << 2651 << 395863 << 1323 << 2707 << 265877; // 2011--2020 lunarData << 1706 << 2773 << 133557 << 1206 << 398510 << 2638 << 3366 << 335142 << 3411 << 1450; // 2021--2030 lunarData << 200042 << 2413 << 723293 << 1197 << 2637 << 399947 << 3365 << 3410 << 334676 << 2906; // 2031--2040 //二十四节气表 chineseTwentyFourData << 0x95 << 0xB4 << 0x96 << 0xA5 << 0x96 << 0x97 << 0x88 << 0x78 << 0x78 << 0x69 << 0x78 << 0x87; // 1970 chineseTwentyFourData << 0x96 << 0xB4 << 0x96 << 0xA6 << 0x97 << 0x97 << 0x78 << 0x79 << 0x79 << 0x69 << 0x78 << 0x77; // 1971 chineseTwentyFourData << 0x96 << 0xA4 << 0xA5 << 0xA5 << 0xA6 << 0xA6 << 0x88 << 0x88 << 0x88 << 0x78 << 0x87 << 0x87; // 1972 chineseTwentyFourData << 0xA5 << 0xB5 << 0x96 << 0xA5 << 0xA6 << 0x96 << 0x88 << 0x78 << 0x78 << 0x78 << 0x87 << 0x87; // 1973 chineseTwentyFourData << 0x95 << 0xB4 << 0x96 << 0xA5 << 0x96 << 0x97 << 0x88 << 0x78 << 0x78 << 0x69 << 0x78 << 0x87; // 1974 chineseTwentyFourData << 0x96 << 0xB4 << 0x96 << 0xA6 << 0x97 << 0x97 << 0x78 << 0x79 << 0x78 << 0x69 << 0x78 << 0x77; // 1975 chineseTwentyFourData << 0x96 << 0xA4 << 0xA5 << 0xB5 << 0xA6 << 0xA6 << 0x88 << 0x89 << 0x88 << 0x78 << 0x87 << 0x87; // 1976 chineseTwentyFourData << 0xA5 << 0xB4 << 0x96 << 0xA5 << 0x96 << 0x96 << 0x88 << 0x88 << 0x78 << 0x78 << 0x87 << 0x87; // 1977 chineseTwentyFourData << 0x95 << 0xB4 << 0x96 << 0xA5 << 0x96 << 0x97 << 0x88 << 0x78 << 0x78 << 0x79 << 0x78 << 0x87; // 1978 chineseTwentyFourData << 0x96 << 0xB4 << 0x96 << 0xA6 << 0x96 << 0x97 << 0x78 << 0x79 << 0x78 << 0x69 << 0x78 << 0x77; // 1979 chineseTwentyFourData << 0x96 << 0xA4 << 0xA5 << 0xB5 << 0xA6 << 0xA6 << 0x88 << 0x88 << 0x88 << 0x78 << 0x87 << 0x87; // 1980 chineseTwentyFourData << 0xA5 << 0xB4 << 0x96 << 0xA5 << 0xA6 << 0x96 << 0x88 << 0x88 << 0x78 << 0x78 << 0x77 << 0x87; // 1981 chineseTwentyFourData << 0x95 << 0xB4 << 0x96 << 0xA5 << 0x96 << 0x97 << 0x88 << 0x78 << 0x78 << 0x79 << 0x77 << 0x87; // 1982 chineseTwentyFourData << 0x95 << 0xB4 << 0x96 << 0xA5 << 0x96 << 0x97 << 0x78 << 0x79 << 0x78 << 0x69 << 0x78 << 0x77; // 1983 chineseTwentyFourData << 0x96 << 0xB4 << 0xA5 << 0xB5 << 0xA6 << 0xA6 << 0x87 << 0x88 << 0x88 << 0x78 << 0x87 << 0x87; // 1984 chineseTwentyFourData << 0xA5 << 0xB4 << 0xA6 << 0xA5 << 0xA6 << 0x96 << 0x88 << 0x88 << 0x78 << 0x78 << 0x87 << 0x87; // 1985 chineseTwentyFourData << 0xA5 << 0xB4 << 0x96 << 0xA5 << 0x96 << 0x97 << 0x88 << 0x78 << 0x78 << 0x79 << 0x77 << 0x87; // 1986 chineseTwentyFourData << 0x95 << 0xB4 << 0x96 << 0xA5 << 0x96 << 0x97 << 0x88 << 0x79 << 0x78 << 0x69 << 0x78 << 0x87; // 1987 chineseTwentyFourData << 0x96 << 0xB4 << 0xA5 << 0xB5 << 0xA6 << 0xA6 << 0x87 << 0x88 << 0x88 << 0x78 << 0x87 << 0x86; // 1988 chineseTwentyFourData << 0xA5 << 0xB4 << 0xA5 << 0xA5 << 0xA6 << 0x96 << 0x88 << 0x88 << 0x88 << 0x78 << 0x87 << 0x87; // 1989 chineseTwentyFourData << 0xA5 << 0xB4 << 0x96 << 0xA5 << 0x96 << 0x96 << 0x88 << 0x78 << 0x78 << 0x79 << 0x77 << 0x87; // 1990 chineseTwentyFourData << 0x95 << 0xB4 << 0x96 << 0xA5 << 0x86 << 0x97 << 0x88 << 0x78 << 0x78 << 0x69 << 0x78 << 0x87; // 1991 chineseTwentyFourData << 0x96 << 0xB4 << 0xA5 << 0xB5 << 0xA6 << 0xA6 << 0x87 << 0x88 << 0x88 << 0x78 << 0x87 << 0x86; // 1992 chineseTwentyFourData << 0xA5 << 0xB3 << 0xA5 << 0xA5 << 0xA6 << 0x96 << 0x88 << 0x88 << 0x88 << 0x78 << 0x87 << 0x87; // 1993 chineseTwentyFourData << 0xA5 << 0xB4 << 0x96 << 0xA5 << 0x96 << 0x96 << 0x88 << 0x78 << 0x78 << 0x78 << 0x87 << 0x87; // 1994 chineseTwentyFourData << 0x95 << 0xB4 << 0x96 << 0xA5 << 0x96 << 0x97 << 0x88 << 0x76 << 0x78 << 0x69 << 0x78 << 0x87; // 1995 chineseTwentyFourData << 0x96 << 0xB4 << 0xA5 << 0xB5 << 0xA6 << 0xA6 << 0x87 << 0x88 << 0x88 << 0x78 << 0x87 << 0x86; // 1996 chineseTwentyFourData << 0xA5 << 0xB3 << 0xA5 << 0xA5 << 0xA6 << 0xA6 << 0x88 << 0x88 << 0x88 << 0x78 << 0x87 << 0x87; // 1997 chineseTwentyFourData << 0xA5 << 0xB4 << 0x96 << 0xA5 << 0x96 << 0x96 << 0x88 << 0x78 << 0x78 << 0x78 << 0x87 << 0x87; // 1998 chineseTwentyFourData << 0x95 << 0xB4 << 0x96 << 0xA5 << 0x96 << 0x97 << 0x88 << 0x78 << 0x78 << 0x69 << 0x78 << 0x87; // 1999 chineseTwentyFourData << 0x96 << 0xB4 << 0xA5 << 0xB5 << 0xA6 << 0xA6 << 0x87 << 0x88 << 0x88 << 0x78 << 0x87 << 0x86; // 2000 chineseTwentyFourData << 0xA5 << 0xB3 << 0xA5 << 0xA5 << 0xA6 << 0xA6 << 0x88 << 0x88 << 0x88 << 0x78 << 0x87 << 0x87; // 2001 chineseTwentyFourData << 0xA5 << 0xB4 << 0x96 << 0xA5 << 0x96 << 0x96 << 0x88 << 0x78 << 0x78 << 0x78 << 0x87 << 0x87; // 2002 chineseTwentyFourData << 0x95 << 0xB4 << 0x96 << 0xA5 << 0x96 << 0x97 << 0x88 << 0x78 << 0x78 << 0x69 << 0x78 << 0x87; // 2003 chineseTwentyFourData << 0x96 << 0xB4 << 0xA5 << 0xB5 << 0xA6 << 0xA6 << 0x87 << 0x88 << 0x88 << 0x78 << 0x87 << 0x86; // 2004 chineseTwentyFourData << 0xA5 << 0xB3 << 0xA5 << 0xA5 << 0xA6 << 0xA6 << 0x88 << 0x88 << 0x88 << 0x78 << 0x87 << 0x87; // 2005 chineseTwentyFourData << 0xA5 << 0xB4 << 0x96 << 0xA5 << 0xA6 << 0x96 << 0x88 << 0x88 << 0x78 << 0x78 << 0x87 << 0x87; // 2006 chineseTwentyFourData << 0x95 << 0xB4 << 0x96 << 0xA5 << 0x96 << 0x97 << 0x88 << 0x78 << 0x78 << 0x69 << 0x78 << 0x87; // 2007 chineseTwentyFourData << 0x96 << 0xB4 << 0xA5 << 0xB5 << 0xA6 << 0xA6 << 0x87 << 0x88 << 0x87 << 0x78 << 0x87 << 0x86; // 2008 chineseTwentyFourData << 0xA5 << 0xB3 << 0xA5 << 0xB5 << 0xA6 << 0xA6 << 0x88 << 0x88 << 0x88 << 0x78 << 0x87 << 0x87; // 2009 chineseTwentyFourData << 0xA5 << 0xB4 << 0x96 << 0xA5 << 0xA6 << 0x96 << 0x88 << 0x88 << 0x78 << 0x78 << 0x87 << 0x87; // 2010 chineseTwentyFourData << 0x95 << 0xB4 << 0x96 << 0xA5 << 0x96 << 0x97 << 0x88 << 0x78 << 0x78 << 0x79 << 0x78 << 0x87; // 2011 chineseTwentyFourData << 0x96 << 0xB4 << 0xA5 << 0xB5 << 0xA5 << 0xA6 << 0x87 << 0x88 << 0x87 << 0x78 << 0x87 << 0x86; // 2012 chineseTwentyFourData << 0xA5 << 0xB3 << 0xA5 << 0xB5 << 0xA6 << 0xA6 << 0x87 << 0x88 << 0x88 << 0x78 << 0x87 << 0x87; // 2013 chineseTwentyFourData << 0xA5 << 0xB4 << 0x96 << 0xA5 << 0xA6 << 0x96 << 0x88 << 0x88 << 0x78 << 0x78 << 0x87 << 0x87; // 2014 chineseTwentyFourData << 0x95 << 0xB4 << 0x96 << 0xA5 << 0x96 << 0x97 << 0x88 << 0x78 << 0x78 << 0x79 << 0x77 << 0x87; // 2015 chineseTwentyFourData << 0x95 << 0xB4 << 0xA5 << 0xB4 << 0xA5 << 0xA6 << 0x87 << 0x88 << 0x87 << 0x78 << 0x87 << 0x86; // 2016 chineseTwentyFourData << 0xA5 << 0xC3 << 0xA5 << 0xB5 << 0xA6 << 0xA6 << 0x87 << 0x88 << 0x88 << 0x78 << 0x87 << 0x87; // 2017 chineseTwentyFourData << 0xA5 << 0xB4 << 0xA6 << 0xA5 << 0xA6 << 0x96 << 0x88 << 0x88 << 0x78 << 0x78 << 0x87 << 0x87; // 2018 chineseTwentyFourData << 0xA5 << 0xB4 << 0x96 << 0xA5 << 0x96 << 0x96 << 0x88 << 0x78 << 0x78 << 0x79 << 0x77 << 0x87; // 2019 chineseTwentyFourData << 0x95 << 0xB4 << 0xA5 << 0xB4 << 0xA5 << 0xA6 << 0x97 << 0x87 << 0x87 << 0x78 << 0x87 << 0x86; // 2020 chineseTwentyFourData << 0xA5 << 0xC3 << 0xA5 << 0xB5 << 0xA6 << 0xA6 << 0x87 << 0x88 << 0x88 << 0x78 << 0x87 << 0x86; // 2021 chineseTwentyFourData << 0xA5 << 0xB4 << 0xA5 << 0xA5 << 0xA6 << 0x96 << 0x88 << 0x88 << 0x88 << 0x78 << 0x87 << 0x87; // 2022 chineseTwentyFourData << 0xA5 << 0xB4 << 0x96 << 0xA5 << 0x96 << 0x96 << 0x88 << 0x78 << 0x78 << 0x79 << 0x77 << 0x87; // 2023 chineseTwentyFourData << 0x95 << 0xB4 << 0xA5 << 0xB4 << 0xA5 << 0xA6 << 0x97 << 0x87 << 0x87 << 0x78 << 0x87 << 0x96; // 2024 chineseTwentyFourData << 0xA5 << 0xC3 << 0xA5 << 0xB5 << 0xA6 << 0xA6 << 0x87 << 0x88 << 0x88 << 0x78 << 0x87 << 0x86; // 2025 chineseTwentyFourData << 0xA5 << 0xB3 << 0xA5 << 0xA5 << 0xA6 << 0xA6 << 0x88 << 0x88 << 0x88 << 0x78 << 0x87 << 0x87; // 2026 chineseTwentyFourData << 0xA5 << 0xB4 << 0x96 << 0xA5 << 0x96 << 0x96 << 0x88 << 0x78 << 0x78 << 0x78 << 0x87 << 0x87; // 2027 chineseTwentyFourData << 0x95 << 0xB4 << 0xA5 << 0xB4 << 0xA5 << 0xA6 << 0x97 << 0x87 << 0x87 << 0x78 << 0x87 << 0x96; // 2028 chineseTwentyFourData << 0xA5 << 0xC3 << 0xA5 << 0xB5 << 0xA6 << 0xA6 << 0x87 << 0x88 << 0x88 << 0x78 << 0x87 << 0x86; // 2029 chineseTwentyFourData << 0xA5 << 0xB3 << 0xA5 << 0xA5 << 0xA6 << 0xA6 << 0x88 << 0x88 << 0x88 << 0x78 << 0x87 << 0x87; // 2030 chineseTwentyFourData << 0xA5 << 0xB4 << 0x96 << 0xA5 << 0x96 << 0x96 << 0x88 << 0x78 << 0x78 << 0x78 << 0x87 << 0x87; // 2031 chineseTwentyFourData << 0x95 << 0xB4 << 0xA5 << 0xB4 << 0xA5 << 0xA6 << 0x97 << 0x87 << 0x87 << 0x78 << 0x87 << 0x96; // 2032 chineseTwentyFourData << 0xA5 << 0xC3 << 0xA5 << 0xB5 << 0xA6 << 0xA6 << 0x88 << 0x88 << 0x88 << 0x78 << 0x87 << 0x86; // 2033 chineseTwentyFourData << 0xA5 << 0xB3 << 0xA5 << 0xA5 << 0xA6 << 0xA6 << 0x88 << 0x78 << 0x88 << 0x78 << 0x87 << 0x87; // 2034 chineseTwentyFourData << 0xA5 << 0xB4 << 0x96 << 0xA5 << 0xA6 << 0x96 << 0x88 << 0x88 << 0x78 << 0x78 << 0x87 << 0x87; // 2035 chineseTwentyFourData << 0x95 << 0xB4 << 0xA5 << 0xB4 << 0xA5 << 0xA6 << 0x97 << 0x87 << 0x87 << 0x78 << 0x87 << 0x96; // 2036 chineseTwentyFourData << 0xA5 << 0xC3 << 0xA5 << 0xB5 << 0xA6 << 0xA6 << 0x87 << 0x88 << 0x88 << 0x78 << 0x87 << 0x86; // 2037 chineseTwentyFourData << 0xA5 << 0xB3 << 0xA5 << 0xA5 << 0xA6 << 0xA6 << 0x88 << 0x88 << 0x88 << 0x78 << 0x87 << 0x87; // 2038 chineseTwentyFourData << 0xA5 << 0xB4 << 0x96 << 0xA5 << 0xA6 << 0x96 << 0x88 << 0x88 << 0x78 << 0x78 << 0x87 << 0x87; // 2039 chineseTwentyFourData << 0x95 << 0xB4 << 0x96 << 0xA5 << 0x96 << 0x97 << 0x88 << 0x78 << 0x78 << 0x69 << 0x78 << 0x87; // 2040 chineseTwentyFourData << 0xA5 << 0xC3 << 0xA5 << 0xB5 << 0xA5 << 0xA6 << 0x87 << 0x88 << 0x87 << 0x78 << 0x87 << 0x86; // 2041 chineseTwentyFourData << 0xA5 << 0xB3 << 0xA5 << 0xB5 << 0xA6 << 0xA6 << 0x88 << 0x88 << 0x88 << 0x78 << 0x87 << 0x87; // 2042 chineseTwentyFourData << 0xA5 << 0xB4 << 0x96 << 0xA5 << 0xA6 << 0x96 << 0x88 << 0x88 << 0x78 << 0x78 << 0x87 << 0x87; // 2043 chineseTwentyFourData << 0x95 << 0xB4 << 0x96 << 0xA5 << 0x96 << 0x97 << 0x88 << 0x78 << 0x78 << 0x79 << 0x78 << 0x87; // 2044 chineseTwentyFourData << 0xA5 << 0xC3 << 0xA5 << 0xB4 << 0xA5 << 0xA6 << 0x87 << 0x88 << 0x87 << 0x78 << 0x87 << 0x86; // 2045 chineseTwentyFourData << 0xA5 << 0xB3 << 0xA5 << 0xB5 << 0xA6 << 0xA6 << 0x87 << 0x88 << 0x88 << 0x78 << 0x87 << 0x87; // 2046 chineseTwentyFourData << 0xA5 << 0xB4 << 0x96 << 0xA5 << 0xA6 << 0x96 << 0x88 << 0x88 << 0x78 << 0x78 << 0x87 << 0x87; // 2047 chineseTwentyFourData << 0x95 << 0xB4 << 0x96 << 0xA5 << 0x96 << 0x96 << 0x88 << 0x78 << 0x78 << 0x79 << 0x77 << 0x87; // 2048 chineseTwentyFourData << 0xA4 << 0xC3 << 0xA5 << 0xB4 << 0xA5 << 0xA6 << 0x97 << 0x87 << 0x87 << 0x78 << 0x87 << 0x86; // 2049 chineseTwentyFourData << 0xA5 << 0xC3 << 0xA5 << 0xB5 << 0xA6 << 0xA6 << 0x87 << 0x88 << 0x88 << 0x78 << 0x87 << 0x87; // 2050 chineseTwentyFourData << 0xA5 << 0xB4 << 0xA5 << 0xA5 << 0xA6 << 0x96 << 0x88 << 0x88 << 0x88 << 0x78 << 0x87 << 0x87; // 2051 chineseTwentyFourData << 0xA5 << 0xB4 << 0x96 << 0xA5 << 0x96 << 0x96 << 0x88 << 0x78 << 0x78 << 0x79 << 0x77 << 0x87; // 2052 chineseTwentyFourData << 0xA4 << 0xC3 << 0xA5 << 0xB4 << 0xA5 << 0xA6 << 0x97 << 0x87 << 0x87 << 0x78 << 0x87 << 0x86; // 2053 chineseTwentyFourData << 0xA5 << 0xC3 << 0xA5 << 0xB5 << 0xA6 << 0xA6 << 0x87 << 0x88 << 0x88 << 0x78 << 0x87 << 0x87; // 2054 chineseTwentyFourData << 0xA5 << 0xB4 << 0xA5 << 0xA5 << 0xA6 << 0xA6 << 0x88 << 0x88 << 0x88 << 0x78 << 0x87 << 0x87; // 2055 chineseTwentyFourData << 0xA5 << 0xB4 << 0x96 << 0xA5 << 0x96 << 0x96 << 0x88 << 0x78 << 0x78 << 0x79 << 0x77 << 0x87; // 2056 chineseTwentyFourData << 0xA4 << 0xC3 << 0xA5 << 0xB4 << 0xA5 << 0xA6 << 0x97 << 0x87 << 0x87 << 0x78 << 0x87 << 0x96; // 2057 chineseTwentyFourData << 0xA5 << 0xC3 << 0xA5 << 0xB5 << 0xA6 << 0xA6 << 0x87 << 0x88 << 0x88 << 0x78 << 0x87 << 0x86; // 2058 chineseTwentyFourData << 0xA5 << 0xB4 << 0xA5 << 0xA5 << 0xA6 << 0xA6 << 0x88 << 0x88 << 0x88 << 0x78 << 0x87 << 0x87; // 2059 chineseTwentyFourData << 0xA5 << 0xB4 << 0x96 << 0xA5 << 0x96 << 0x96 << 0x88 << 0x78 << 0x78 << 0x78 << 0x87 << 0x87; // 2060 chineseTwentyFourData << 0xA4 << 0xC3 << 0xA5 << 0xB4 << 0xA5 << 0xA6 << 0x97 << 0x87 << 0x87 << 0x78 << 0x87 << 0x96; // 2061 chineseTwentyFourData << 0xA5 << 0xC3 << 0xA5 << 0xB5 << 0xA6 << 0xA6 << 0x87 << 0x88 << 0x88 << 0x78 << 0x87 << 0x86; // 2062 chineseTwentyFourData << 0xA5 << 0xB3 << 0xA5 << 0xA5 << 0xA6 << 0xA6 << 0x88 << 0x88 << 0x88 << 0x78 << 0x87 << 0x87; // 2063 chineseTwentyFourData << 0xA5 << 0xB4 << 0x96 << 0xA5 << 0x96 << 0x96 << 0x88 << 0x78 << 0x78 << 0x78 << 0x87 << 0x87; // 2064 chineseTwentyFourData << 0xA4 << 0xC3 << 0xA5 << 0xB4 << 0xA5 << 0xA6 << 0x97 << 0x87 << 0x87 << 0x78 << 0x87 << 0x96; // 2065 chineseTwentyFourData << 0xA5 << 0xC3 << 0xA5 << 0xB5 << 0xA6 << 0xA6 << 0x87 << 0x88 << 0x88 << 0x78 << 0x87 << 0x86; // 2066 chineseTwentyFourData << 0xA5 << 0xB3 << 0xA5 << 0xA5 << 0xA6 << 0xA6 << 0x88 << 0x88 << 0x88 << 0x78 << 0x87 << 0x87; // 2067 chineseTwentyFourData << 0xA5 << 0xB4 << 0x96 << 0xA5 << 0xA6 << 0x96 << 0x88 << 0x88 << 0x78 << 0x78 << 0x87 << 0x87; // 2068 chineseTwentyFourData << 0xA4 << 0xC3 << 0xA5 << 0xB4 << 0xA5 << 0xA6 << 0x97 << 0x87 << 0x87 << 0x78 << 0x87 << 0x96; // 2069 chineseTwentyFourData << 0xA5 << 0xC3 << 0xA5 << 0xB5 << 0xA5 << 0xA6 << 0x87 << 0x88 << 0x87 << 0x78 << 0x87 << 0x86; // 2070 chineseTwentyFourData << 0xA5 << 0xB3 << 0xA5 << 0xA5 << 0xA6 << 0xA6 << 0x88 << 0x88 << 0x88 << 0x78 << 0x87 << 0x87; // 2071 chineseTwentyFourData << 0xA5 << 0xB4 << 0x96 << 0xA5 << 0xA6 << 0x96 << 0x88 << 0x88 << 0x78 << 0x78 << 0x87 << 0x87; // 2072 chineseTwentyFourData << 0xA4 << 0xC3 << 0xA5 << 0xB4 << 0xA5 << 0xA6 << 0x97 << 0x87 << 0x87 << 0x88 << 0x87 << 0x96; // 2073 chineseTwentyFourData << 0xA5 << 0xC3 << 0xA5 << 0xB5 << 0xA5 << 0xA6 << 0x87 << 0x88 << 0x87 << 0x78 << 0x87 << 0x86; // 2074 chineseTwentyFourData << 0xA5 << 0xB3 << 0xA5 << 0xB5 << 0xA6 << 0xA6 << 0x87 << 0x88 << 0x88 << 0x78 << 0x87 << 0x87; // 2075 chineseTwentyFourData << 0xA5 << 0xB4 << 0x96 << 0xA5 << 0xA6 << 0x96 << 0x88 << 0x88 << 0x78 << 0x78 << 0x87 << 0x87; // 2076 chineseTwentyFourData << 0xA4 << 0xC3 << 0xA5 << 0xB4 << 0xA5 << 0xA6 << 0x97 << 0x87 << 0x87 << 0x88 << 0x87 << 0x96; // 2077 chineseTwentyFourData << 0xA5 << 0xC3 << 0xA5 << 0xB4 << 0xA5 << 0xA6 << 0x97 << 0x88 << 0x87 << 0x78 << 0x87 << 0x86; // 2078 chineseTwentyFourData << 0xA5 << 0xB3 << 0xA5 << 0xB5 << 0xA6 << 0xA6 << 0x87 << 0x88 << 0x88 << 0x78 << 0x87 << 0x87; // 2079 chineseTwentyFourData << 0xA5 << 0xB4 << 0x96 << 0xA5 << 0xA6 << 0x96 << 0x88 << 0x88 << 0x78 << 0x78 << 0x87 << 0x87; // 2080 chineseTwentyFourData << 0xA4 << 0xC3 << 0xA5 << 0xB4 << 0xA5 << 0xA5 << 0x97 << 0x87 << 0x87 << 0x88 << 0x86 << 0x96; // 2081 chineseTwentyFourData << 0xA5 << 0xC3 << 0xA5 << 0xB4 << 0xA5 << 0xA6 << 0x97 << 0x87 << 0x87 << 0x78 << 0x87 << 0x86; // 2082 chineseTwentyFourData << 0xA5 << 0xC3 << 0xA5 << 0xB5 << 0xA6 << 0xA6 << 0x87 << 0x88 << 0x88 << 0x78 << 0x87 << 0x87; // 2083 chineseTwentyFourData << 0xA5 << 0xB4 << 0xA6 << 0xA5 << 0xA6 << 0x96 << 0x88 << 0x88 << 0x88 << 0x78 << 0x87 << 0x87; // 2084 chineseTwentyFourData << 0xB4 << 0xC3 << 0xA5 << 0xB4 << 0xA5 << 0xA5 << 0x97 << 0x87 << 0x87 << 0x88 << 0x86 << 0x96; // 2085 chineseTwentyFourData << 0xA4 << 0xC3 << 0xA5 << 0xB4 << 0xA5 << 0xA6 << 0x97 << 0x87 << 0x87 << 0x78 << 0x87 << 0x86; // 2086 chineseTwentyFourData << 0xA5 << 0xC3 << 0xA5 << 0xB5 << 0xA6 << 0xA6 << 0x87 << 0x88 << 0x88 << 0x78 << 0x87 << 0x87; // 2087 chineseTwentyFourData << 0xA5 << 0xB4 << 0xA5 << 0xA5 << 0xA6 << 0xA6 << 0x88 << 0x88 << 0x88 << 0x78 << 0x87 << 0x87; // 2088 chineseTwentyFourData << 0xB4 << 0xC3 << 0xA5 << 0xB4 << 0xA5 << 0xA5 << 0x97 << 0x87 << 0x87 << 0x88 << 0x96 << 0x96; // 2089 chineseTwentyFourData << 0xA4 << 0xC3 << 0xA5 << 0xB4 << 0xA5 << 0xA6 << 0x97 << 0x87 << 0x87 << 0x78 << 0x87 << 0x96; // 2090 chineseTwentyFourData << 0xA5 << 0xC3 << 0xA5 << 0xB5 << 0xA6 << 0xA6 << 0x87 << 0x88 << 0x88 << 0x78 << 0x87 << 0x86; // 2091 chineseTwentyFourData << 0xA5 << 0xB4 << 0xA5 << 0xA5 << 0xA6 << 0xA6 << 0x88 << 0x88 << 0x88 << 0x78 << 0x87 << 0x87; // 2092 chineseTwentyFourData << 0xB4 << 0xC3 << 0xA5 << 0xB4 << 0xA5 << 0xA5 << 0x97 << 0x87 << 0x87 << 0x87 << 0x96 << 0x96; // 2093 chineseTwentyFourData << 0xA4 << 0xC3 << 0xA5 << 0xB4 << 0xA5 << 0xA6 << 0x97 << 0x87 << 0x87 << 0x78 << 0x87 << 0x96; // 2094 chineseTwentyFourData << 0xA5 << 0xC3 << 0xA5 << 0xB5 << 0xA6 << 0xA6 << 0x87 << 0x88 << 0x88 << 0x78 << 0x87 << 0x86; // 2095 chineseTwentyFourData << 0xA5 << 0xB3 << 0xA5 << 0xA5 << 0xA6 << 0xA6 << 0x88 << 0x88 << 0x88 << 0x78 << 0x87 << 0x87; // 2096 chineseTwentyFourData << 0xB4 << 0xC3 << 0xA5 << 0xB4 << 0xA5 << 0xA5 << 0x97 << 0x97 << 0x87 << 0x87 << 0x96 << 0x96; // 2097 chineseTwentyFourData << 0xA4 << 0xC3 << 0xA5 << 0xB4 << 0xA5 << 0xA6 << 0x97 << 0x87 << 0x87 << 0x78 << 0x87 << 0x96; // 2098 chineseTwentyFourData << 0xA5 << 0xC3 << 0xA5 << 0xB5 << 0xA6 << 0xA6 << 0x87 << 0x88 << 0x88 << 0x78 << 0x87 << 0x86; // 2099 //公历每月前面的天数 monthAdd << 0 << 31 << 59 << 90 << 120 << 151 << 181 << 212 << 243 << 273 << 304 << 334; //农历日期名称 listDayName << "*" << "初一" << "初二" << "初三" << "初四" << "初五" << "初六" << "初七" << "初八" << "初九" << "初十" << "十一" << "十二" << "十三" << "十四" << "十五" << "十六" << "十七" << "十八" << "十九" << "二十" << "廿一" << "廿二" << "廿三" << "廿四" << "廿五" << "廿六" << "廿七" << "廿八" << "廿九" << "三十"; //农历月份名称 listMonthName << "*" << "正月" << "二月" << "三月" << "四月" << "五月" << "六月" << "七月" << "八月" << "九月" << "十月" << "冬月" << "腊月"; //二十四节气名称 listSolarTerm << "小寒" << "大寒" << "立春" << "雨水" << "惊蛰" << "春分" << "清明" << "谷雨" << "立夏" << "小满" << "芒种" << "夏至" << "小暑" << "大暑" << "立秋" << "处暑" << "白露" << "秋分" << "寒露" << "霜降" << "立冬" << "小雪" << "大雪" << "冬至"; //天干 listTianGan << "甲" << "乙" << "丙" << "丁" << "戊" << "己" << "庚" << "辛" << "壬" << "癸"; //地支 listDiZhi << "子" << "丑" << "寅" << "卯" << "辰" << "巳" << "午" << "未" << "申" << "酉" << "戌" << "亥"; //属相 listShuXiang << "鼠" << "牛" << "虎" << "兔" << "龙" << "蛇" << "马" << "羊" << "猴" << "鸡" << "狗" << "猪"; } //计算是否闰年 bool LunarCalendarInfo::isLoopYear(int year) { return (((0 == (year % 4)) && (0 != (year % 100))) || (0 == (year % 400))); } //计算指定年月该月共多少天 int LunarCalendarInfo::getMonthDays(int year, int month) { int countDay = 0; int loopDay = isLoopYear(year) ? 1 : 0; switch (month) { case 1: countDay = 31; break; case 2: countDay = 28 + loopDay; break; case 3: countDay = 31; break; case 4: countDay = 30; break; case 5: countDay = 31; break; case 6: countDay = 30; break; case 7: countDay = 31; break; case 8: countDay = 31; break; case 9: countDay = 30; break; case 10: countDay = 31; break; case 11: countDay = 30; break; case 12: countDay = 31; break; default: countDay = 30; break; } return countDay; } //计算指定年月对应到该月共多少天 int LunarCalendarInfo::getTotalMonthDays(int year, int month) { int countDay = 0; int loopDay = isLoopYear(year) ? 1 : 0; switch (month) { case 1: countDay = 0; break; case 2: countDay = 31; break; case 3: countDay = 59 + loopDay; break; case 4: countDay = 90 + loopDay; break; case 5: countDay = 120 + loopDay; break; case 6: countDay = 151 + loopDay; break; case 7: countDay = 181 + loopDay; break; case 8: countDay = 212 + loopDay; break; case 9: countDay = 243 + loopDay; break; case 10: countDay = 273 + loopDay; break; case 11: countDay = 304 + loopDay; break; case 12: countDay = 334 + loopDay; break; default: countDay = 0; break; } return countDay; } //计算指定年月对应星期几 int LunarCalendarInfo::getFirstDayOfWeek(int year, int month, bool FirstDayisSun) { int week = 0; week = (year + (year - 1) / 4 - (year - 1) / 100 + (year - 1) / 400) % 7; week += getTotalMonthDays(year, month); week = week % 7 - (!FirstDayisSun); if (week == -1) week = 6; return week; } //计算国际节日 QString LunarCalendarInfo::getHoliday(int month, int day) { int temp = (month << 8) | day; QString strHoliday; switch (temp) { case 0x0101: strHoliday = "元旦"; break; case 0x020E: strHoliday = "情人节"; break; case 0x0305: strHoliday = "志愿者"; break; case 0x0308: strHoliday = "妇女节"; break; case 0x030C: strHoliday = "植树节"; break; case 0x0401: strHoliday = "愚人节"; break; case 0x0501: strHoliday = "劳动节"; break; case 0x0504: strHoliday = "青年节"; break; case 0x0601: strHoliday = "儿童节"; break; case 0x0606: strHoliday = "爱眼日"; break; case 0x0701: strHoliday = "建党节"; break; case 0x0707: strHoliday = "抗战日"; break; case 0x0801: strHoliday = "建军节"; break; case 0x090A: strHoliday = "教师节"; break; case 0x0A01: strHoliday = "国庆节"; break; case 0x0B08: strHoliday = "记者节"; break; case 0x0B09: strHoliday = "消防日"; break; case 0x0C18: strHoliday = "平安夜"; break; case 0x0C19: strHoliday = "圣诞节"; break; default: break; } return strHoliday; } //计算二十四节气 QString LunarCalendarInfo::getSolarTerms(int year, int month, int day) { QString strSolarTerms; int dayTemp = 0; int index = (year - 1970) * 12 + month - 1; if (day < 15) { dayTemp = 15 - day; if ((chineseTwentyFourData.at(index) >> 4) == dayTemp) { strSolarTerms = listSolarTerm.at(2 * (month - 1)); } } else if (day > 15) { dayTemp = day - 15; if ((chineseTwentyFourData.at(index) & 0x0f) == dayTemp) { strSolarTerms = listSolarTerm.at(2 * (month - 1) + 1); } } return strSolarTerms; } //计算农历节日(必须传入农历年份月份) QString LunarCalendarInfo::getLunarFestival(int month, int day) { int temp = (month << 8) | day; QString strFestival; switch (temp) { case 0x0201: strFestival = "二月"; break; case 0x0301: strFestival = "三月"; break; case 0x0401: strFestival = "四月"; break; case 0x0501: strFestival = "五月"; break; case 0x0601: strFestival = "六月"; break; case 0x0701: strFestival = "七月"; break; case 0x0801: strFestival = "八月"; break; case 0x0901: strFestival = "九月"; break; case 0x0A01: strFestival = "十月"; break; case 0x0B01: strFestival = "冬月"; break; case 0x0C01: strFestival = "腊月"; break; case 0x0101: strFestival = "春节"; break; case 0x010F: strFestival = "元宵节"; break; case 0x0202: strFestival = "龙抬头"; break; case 0x0505: strFestival = "端午节"; break; case 0x0707: strFestival = "七夕节"; break; case 0x080F: strFestival = "中秋节"; break; case 0x0909: strFestival = "重阳节"; break; case 0x0C08: strFestival = "腊八节"; break; case 0x0C1E: strFestival = "除夕"; break; default: break; } return strFestival; } //计算农历年 天干+地支+生肖 QString LunarCalendarInfo::getLunarYear(int year) { QString strYear; if (year > 1924) { int temp = year - 1924; strYear.append(listTianGan.at(temp % 10)); strYear.append(listDiZhi.at(temp % 12)); strYear.append("年"); strYear.append(listShuXiang.at(temp % 12)); strYear.append("年"); } return strYear; } void LunarCalendarInfo::getLunarCalendarInfo(int year, int month, int day, QString &strHoliday, QString &strSolarTerms, QString &strLunarFestival, QString &strLunarYear, QString &strLunarMonth, QString &strLunarDay) { //过滤不在范围内的年月日 if (year < 1901 || year > 2099 || month < 1 || month > 12 || day < 1 || day > 31) { return; } strHoliday = getHoliday(month, day); strSolarTerms = getSolarTerms(year, month, day); #ifndef year_2099 //现在计算农历:获得当年春节的公历日期(比如:2015年春节日期为(2月19日)) //以此为分界点,2.19前面的农历是2014年农历(用2014年农历数据来计算) //2.19以及之后的日期,农历为2015年农历(用2015年农历数据来计算) int temp, tempYear, tempMonth, isEnd, k, n; tempMonth = year - 1968; int springFestivalMonth = springFestival.at(tempMonth) / 100; int springFestivalDaty = springFestival.at(tempMonth) % 100; if (month < springFestivalMonth) { tempMonth--; tempYear = 365 * 1 + day + monthAdd.at(month - 1) - 31 * ((springFestival.at(tempMonth) / 100) - 1) - springFestival.at(tempMonth) % 100 + 1; if ((!(year % 4)) && (month > 2)) { tempYear = tempYear + 1; } if ((!((year - 1) % 4))) { tempYear = tempYear + 1; } } else if (month == springFestivalMonth) { if (day < springFestivalDaty) { tempMonth--; tempYear = 365 * 1 + day + monthAdd.at(month - 1) - 31 * ((springFestival.at(tempMonth) / 100) - 1) - springFestival.at(tempMonth) % 100 + 1; if ((!(year % 4)) && (month > 2)) { tempYear = tempYear + 1; } if ((!((year - 1) % 4))) { tempYear = tempYear + 1; } } else { tempYear = day + monthAdd.at(month - 1) - 31 * ((springFestival.at(tempMonth) / 100) - 1) - springFestival.at(tempMonth) % 100 + 1; if ((!(year % 4)) && (month > 2)) { tempYear = tempYear + 1; } } } else { tempYear = day + monthAdd.at(month - 1) - 31 * ((springFestival.at(tempMonth) / 100) - 1) - springFestival.at(tempMonth) % 100 + 1; if ((!(year % 4)) && (month > 2)) { tempYear = tempYear + 1; } } //计算农历天干地支月日 isEnd = 0; while (isEnd != 1) { if (lunarData.at(tempMonth) < 4095) { k = 11; } else { k = 12; } n = k; while (n >= 0) { temp = lunarData.at(tempMonth); temp = temp >> n; temp = temp % 2; if (tempYear <= (29 + temp)) { isEnd = 1; break; } tempYear = tempYear - 29 - temp; n = n - 1; } if (isEnd) { break; } tempMonth = tempMonth + 1; } //农历的年月日 year = 1969 + tempMonth - 1; month = k - n + 1; day = tempYear; if (k == 12) { if (month == (lunarData.at(tempMonth) / 65536) + 1) { month = 1 - month; } else if (month > (lunarData.at(tempMonth) / 65536) + 1) { month = month - 1; } } strLunarYear = getLunarYear(year); if (month < 1 && (1 == day)) { month = month * -1; strLunarMonth = "闰" + listMonthName.at(month); } else { strLunarMonth = listMonthName.at(month); } strLunarDay = listDayName.at(day); strLunarFestival = getLunarFestival(month, day); #else //记录春节离当年元旦的天数 int springOffset = 0; //记录阳历日离当年元旦的天数 int newYearOffset = 0; //记录大小月的天数 29或30 int monthCount = 0; if(((lunarCalendarTable.at(year - 1901) & 0x0060) >> 5) == 1) { springOffset = (lunarCalendarTable.at(year - 1901) & 0x001F) - 1; } else { springOffset = (lunarCalendarTable.at(year - 1901) & 0x001F) - 1 + 31; } //如果是不闰年且不是2月份 +1 newYearOffset = monthAdd.at(month - 1) + day - 1; if((!(year % 4)) && (month > 2)) { newYearOffset++; } //记录从哪个月开始来计算 int index = 0; //用来对闰月的特殊处理 int flag = 0; //判断阳历日在春节前还是春节后,计算农历的月/日 if (newYearOffset >= springOffset) { newYearOffset -= springOffset; month = 1; index = 1; flag = 0; if((lunarCalendarTable.at(year - 1901) & (0x80000 >> (index - 1))) == 0) { monthCount = 29; } else { monthCount = 30; } while (newYearOffset >= monthCount) { newYearOffset -= monthCount; index++; if (month == ((lunarCalendarTable.at(year - 1901) & 0xF00000) >> 20) ) { flag = ~flag; if (flag == 0) { month++; } } else { month++; } if ((lunarCalendarTable.at(year - 1901) & (0x80000 >> (index - 1))) == 0) { monthCount = 29; } else { monthCount = 30; } } day = newYearOffset + 1; } else { springOffset -= newYearOffset; year--; month = 12; flag = 0; if (((lunarCalendarTable.at(year - 1901) & 0xF00000) >> 20) == 0) { index = 12; } else { index = 13; } if ((lunarCalendarTable.at(year - 1901) & (0x80000 >> (index - 1))) == 0) { monthCount = 29; } else { monthCount = 30; } while (springOffset > monthCount) { springOffset -= monthCount; index--; if(flag == 0) { month--; } if(month == ((lunarCalendarTable.at(year - 1901) & 0xF00000) >> 20)) { flag = ~flag; } if ((lunarCalendarTable.at(year - 1901) & (0x80000 >> (index - 1))) == 0) { monthCount = 29; } else { monthCount = 30; } } day = monthCount - springOffset + 1; } //计算农历的索引配置 int temp = 0; temp |= day; temp |= (month << 6); //转换农历的年月 month = (temp & 0x3C0) >> 6; day = temp & 0x3F; strLunarYear = getLunarYear(year); if ((month == ((lunarCalendarTable.at(year - 1901) & 0xF00000) >> 20)) && (1 == day)) { strLunarMonth = "闰" + listMonthName.at(month); } else { strLunarMonth = listMonthName.at(month); } strLunarDay = listDayName.at(day); strLunarFestival = getLunarFestival(month, day); #endif } QString LunarCalendarInfo::getLunarInfo(int year, int month, int day, bool yearInfo, bool monthInfo, bool dayInfo) { QString strHoliday, strSolarTerms, strLunarFestival, strLunarYear, strLunarMonth, strLunarDay; LunarCalendarInfo::Instance()->getLunarCalendarInfo(year, month, day, strHoliday, strSolarTerms, strLunarFestival, strLunarYear, strLunarMonth, strLunarDay); //农历节日优先,其次农历节气,然后公历节日,最后才是农历月份名称 if (!strLunarFestival.isEmpty()) { strLunarDay = strLunarFestival; } else if (!strSolarTerms.isEmpty()) { strLunarDay = strSolarTerms; } else if (!strHoliday.isEmpty()) { strLunarDay = strHoliday; } QString info = QString("%1%2%3") .arg(yearInfo ? strLunarYear + "年" : "") .arg(monthInfo ? strLunarMonth : "") .arg(dayInfo ? strLunarDay : ""); return info; } QString LunarCalendarInfo::getLunarYearMonthDay(int year, int month, int day) { return getLunarInfo(year, month, day, true, true, true); } QString LunarCalendarInfo::getLunarMonthDay(int year, int month, int day) { return getLunarInfo(year, month, day, false, true, true); } QString LunarCalendarInfo::getLunarDay(int year, int month, int day) { return getLunarInfo(year, month, day, false, false, true); } ukui-panel-3.0.6.4/plugin-calendar/lunarcalendarwidget/customstylePushbutton.h0000644000175000017500000000775614203402514026312 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * 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 3, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see class CustomStyle_pushbutton : public QProxyStyle { Q_OBJECT public: explicit CustomStyle_pushbutton(const QString &proxyStyleName = "windows", QObject *parent = nullptr); virtual void drawComplexControl(QStyle::ComplexControl control, const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget = nullptr) const; virtual void drawControl(QStyle::ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget = nullptr) const; virtual void drawItemPixmap(QPainter *painter, const QRect &rectangle, int alignment, const QPixmap &pixmap) const; virtual void drawItemText(QPainter *painter, const QRect &rectangle, int alignment, const QPalette &palette, bool enabled, const QString &text, QPalette::ColorRole textRole = QPalette::NoRole) const; /*! * \brief drawPrimitive * \param element 背景绘制,对应PE枚举类型 * \param option * \param painter * \param widget * \details * drawPrimitive用于绘制控件背景,比如按钮和菜单的背景, * 我们一般需要判断控件的状态来绘制不同的背景, * 比如按钮的hover和点击效果。 */ virtual void drawPrimitive(QStyle::PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget = nullptr) const; virtual QPixmap generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap, const QStyleOption *option) const; virtual QStyle::SubControl hitTestComplexControl(QStyle::ComplexControl control, const QStyleOptionComplex *option, const QPoint &position, const QWidget *widget = nullptr) const; virtual QRect itemPixmapRect(const QRect &rectangle, int alignment, const QPixmap &pixmap) const; virtual QRect itemTextRect(const QFontMetrics &metrics, const QRect &rectangle, int alignment, bool enabled, const QString &text) const; //virtual int layoutSpacing(QSizePolicy::ControlType control1, QSizePolicy::ControlType control2, Qt::Orientation orientation, const QStyleOption *option, const QWidget *widget); virtual int pixelMetric(QStyle::PixelMetric metric, const QStyleOption *option = nullptr, const QWidget *widget = nullptr) const; virtual void polish(QWidget *widget); virtual void polish(QApplication *application); virtual void polish(QPalette &palette); virtual void unpolish(QWidget *widget); virtual void unpolish(QApplication *application); virtual QSize sizeFromContents(QStyle::ContentsType type, const QStyleOption *option, const QSize &contentsSize, const QWidget *widget = nullptr) const; virtual QIcon standardIcon(QStyle::StandardPixmap standardIcon, const QStyleOption *option, const QWidget *widget) const; virtual QPalette standardPalette() const; virtual int styleHint(QStyle::StyleHint hint, const QStyleOption *option = nullptr, const QWidget *widget = nullptr, QStyleHintReturn *returnData = nullptr) const; virtual QRect subControlRect(QStyle::ComplexControl control, const QStyleOptionComplex *option, QStyle::SubControl subControl, const QWidget *widget = nullptr) const; virtual QRect subElementRect(QStyle::SubElement element, const QStyleOption *option, const QWidget *widget = nullptr) const; }; #endif // CUSTOMSTYLE_PUSHBUTTON_H ukui-panel-3.0.6.4/plugin-calendar/lunarcalendarwidget/main.cpp0000644000175000017500000000302114203402514023057 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include int main(int argc, char *argv[]) { QApplication a(argc, argv); a.setFont(QFont("Microsoft Yahei", 9)); #if (QT_VERSION <= QT_VERSION_CHECK(5,0,0)) #if _MSC_VER QTextCodec *codec = QTextCodec::codecForName("gbk"); #else QTextCodec *codec = QTextCodec::codecForName("utf-8"); #endif QTextCodec::setCodecForLocale(codec); QTextCodec::setCodecForCStrings(codec); QTextCodec::setCodecForTr(codec); #else QTextCodec *codec = QTextCodec::codecForName("utf-8"); QTextCodec::setCodecForLocale(codec); #endif frmLunarCalendarWidget w; w.setWindowTitle("自定义农历控件"); w.show(); return a.exec(); } ukui-panel-3.0.6.4/plugin-calendar/resources/0000755000175000017500000000000014203402514017426 5ustar fengfengukui-panel-3.0.6.4/plugin-calendar/resources/calendar.desktop.in0000644000175000017500000000022014203402514023171 0ustar fengfeng[Desktop Entry] Type=Service ServiceTypes=UKUIPanel/Plugin Name=calendar Comment=calendar plugin. Icon=clock #TRANSLATIONS_DIR=../translations ukui-panel-3.0.6.4/plugin-calendar/CMakeLists.txt0000644000175000017500000000314314203402514020155 0ustar fengfeng set(PLUGIN "calendar") if(CMAKE_COMPILER_IS_GNUCXX) set(CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}") message(STATUS "optional:-std=c++11") endif(CMAKE_COMPILER_IS_GNUCXX) set(HEADERS ukuicalendar.h ukuiwebviewdialog.h lunarcalendarwidget/frmlunarcalendarwidget.h lunarcalendarwidget/lunarcalendarinfo.h lunarcalendarwidget/lunarcalendaritem.h lunarcalendarwidget/lunarcalendaryearitem.h lunarcalendarwidget/lunarcalendarmonthitem.h lunarcalendarwidget/lunarcalendarwidget.h lunarcalendarwidget/picturetowhite.h lunarcalendarwidget/customstylePushbutton.h ) set(SOURCES ukuicalendar.cpp ukuiwebviewdialog.cpp lunarcalendarwidget/frmlunarcalendarwidget.cpp lunarcalendarwidget/lunarcalendarinfo.cpp lunarcalendarwidget/lunarcalendaritem.cpp lunarcalendarwidget/lunarcalendaryearitem.cpp lunarcalendarwidget/lunarcalendarmonthitem.cpp lunarcalendarwidget/lunarcalendarwidget.cpp lunarcalendarwidget/picturetowhite.cpp lunarcalendarwidget/customstylePushbutton.cpp ) set(UIS ukuiwebviewdialog.ui lunarcalendarwidget/frmlunarcalendarwidget.ui ) find_package(PkgConfig) pkg_check_modules(Gsetting REQUIRED gsettings-qt) pkg_check_modules(CALENDAR_DEPS REQUIRED glib-2.0) include_directories(${CALENDAR_DEPS_INCLUDE_DIRS}) include_directories(${Gsetting_INCLUDE_DIRS}) ADD_DEFINITIONS(-DQT_NO_KEYWORDS) link_libraries(glib-2.0.so) include(../cmake/UkuiPluginTranslationTs.cmake) ukui_plugin_translate_ts(${PLUGIN}) install(DIRECTORY html/ DESTINATION ${PACKAGE_DATA_DIR}/plugin-calendar/html) BUILD_UKUI_PLUGIN(${PLUGIN}) ukui-panel-3.0.6.4/plugin-calendar/html/0000755000175000017500000000000014204636772016400 5ustar fengfengukui-panel-3.0.6.4/plugin-calendar/html/ukui-mon.html0000644000175000017500000001520714204636772021037 0ustar fengfeng

12:42:53

2020年1月1日 星期三 腊月初七

2020年3月
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
  1. 甲午年【马年】丙子月 庚辰日
宜忌
ukui-panel-3.0.6.4/plugin-calendar/html/index-es.js0000644000175000017500000004136114204636772020457 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see div_range.year.x_max || x < div_range.year.x_min || y > div_range.year.y_max || y < div_range.year.y_min) { year_div.className = 'hidden_div'; } } if (month_div.className === 'visible_div') { if (x > div_range.month.x_max || x < div_range.month.x_min || y > div_range.month.y_max || y < div_range.month.y_min ) { month_div.className = 'hidden_div'; } } /* if (holiday_div.className === 'visible_div') { if (x > div_range.holiday.x_max || x < div_range.holiday.x_min || y > div_range.holiday.y_max || y < div_range.holiday.y_min ) { holiday_div.className = 'hidden_div'; } }*/ }); for (var index = year_range['low']; index <= year_range['high']; index++) { var li = document.createElement('LI'); li.innerHTML = index; li.addEventListener('click', new_month_selected); // new year implies new month year_list.appendChild(li); if (index === year) { year_selector.value = index; } } for (var index = 1; index <= 12; index++) { var li = document.createElement('LI'); li.innerHTML = index; li.addEventListener('click', new_month_selected); month_list.appendChild(li); if (index === month + 1) { month_selector.value = index; } } var goto_arrows = document.getElementsByTagName('input'); var n_months = (year_range['high'] - year_range['low'] + 1) * 12; for (var index = 0; index < goto_arrows.length; index++) { goto_arrows[index].addEventListener('click', function() { var year = parseInt(year_selector.value); var month = parseInt(month_selector.value); var month_offset = (year - year_range['low']) * 12 + month - 1; // [0, n_months - 1] if (this.id === 'go_prev_year') { month_offset -= 12; } else if (this.id === 'go_next_year') { month_offset += 12; } else if (this.id === 'go_prev_month') { month_offset -= 1; } else if (this.id === 'go_next_month') { month_offset += 1; } else { return; } if (month_offset < 0 || month_offset > n_months - 1) { return; } year_selector.value = Math.floor(month_offset / 12) + year_range['low']; month_selector.value = month_offset % 12 === 0 ? 1 : month_offset % 12 + 1; create_page(parseInt(year_selector.value), parseInt(month_selector.value)); }); } /* var holidays = ['元旦节', '春节', '清明节', '劳动节', '端午节', '中秋节', '国庆节']; var holiday_list = document.getElementById('holiday_list'); for (var index = 0; index < holidays.length; index++) { var li = document.createElement('LI'); li.innerHTML = holidays[index]; li.addEventListener('click', go_to_holiday); holiday_list.appendChild(li); }*/ // var holiday_button = document.getElementById('holiday_button'); // holiday_button.addEventListener('click', popup_div); var today_button = document.getElementById('today_button'); today_button.addEventListener('click', function() { year_selector.value = today.getFullYear(); month_selector.value = today.getMonth() + 1; highlight_day = today.getDate(); create_page(today.getFullYear(), today.getMonth() + 1); }); calendar = document.getElementById('calendar_table'); create_page(parseInt(year_selector.value), parseInt(month_selector.value)); } function create_page(year, month) { if (year < year_range['low'] || year > year_range['high']) return; var month_stuff = LunarCalendar.calendar(year, month, true); highlight_day = highlight_day > month_stuff['monthDays'] ? month_stuff['monthDays'] : highlight_day; var current_row = null; var current_cell = null; for (var row = 1; row < 7; row++) { if (calendar.rows.length === row) { current_row = calendar.insertRow(row); } else { current_row = calendar.rows[row]; } for (var column = 0; column < 7; column++) { if (current_row.cells.length === column) { current_cell = current_row.insertCell(column); current_cell.addEventListener('click', function() { highlight_day = parseInt(this.children[0].innerHTML); if (this.className === 'day_other_month') { return; } create_page(parseInt(year_selector.value), parseInt(month_selector.value)); }); } else { current_cell = current_row.cells[column]; } var index = (row - 1) * 7 + column; // [0, 7 * 6 - 1] /* * 注意判断顺序 * 1. 表格开头/结尾的非本月日期的单元格样式与其他单元格无关,需要最先判断 * 2. 其次是‘今天’的单元格样式 * 3. 再次是当前鼠标点击选中的单元格 * 4. 再次是属于周末的单元格 * 5. 最后是其他普通单元格 */ if (index < month_stuff['firstDay'] || index >= month_stuff['firstDay'] + month_stuff['monthDays']) { current_cell.className = 'day_other_month'; } else if (today.getDate() === month_stuff['monthData'][index]['day'] && today.getMonth() === month - 1 && today.getFullYear() === year) { current_cell.className = 'day_today'; } else if (index === highlight_day + month_stuff['firstDay'] - 1) { current_cell.className = 'day_highlight'; } else if (column === 0 || column === 6) { current_cell.className = 'day_weekend'; } else { current_cell.className = 'day_this_month'; } var lunar_day; if (month_stuff['monthData'][index]['lunarFestival']) { lunar_day = month_stuff['monthData'][index]['lunarFestival']; // } else if (month_stuff['monthData'][index]['solarFestival']) { // lunar_day = month_stuff['monthData'][index]['solarFestival']; } else { lunar_day = month_stuff['monthData'][index]['lunarDayName']; } var worktime = null; if (month_stuff['monthData'][index]['worktime'] === 2) { // worktime = document.createElement("SPAN"); worktime.className = 'worktime2'; // worktime.innerHTML = '休'; } else if (month_stuff['monthData'][index]['worktime'] === 1) { // worktime = document.createElement("SPAN"); worktime.className = 'worktime1'; // worktime.innerHTML = '班'; } else { } current_cell.innerHTML = '' + month_stuff['monthData'][index]['day'] + '' + '
' + '' + ''; if (worktime && current_cell.className !== 'day_other_month') { // current_cell.appendChild(worktime); } } } update_right_pane(year, month, highlight_day); month_stuff = null; } function new_month_selected() { if (this.parentNode.id === 'year_list') { year_selector.value = this.innerHTML; document.getElementById('year_div').className = 'hidden_div'; } else if (this.parentNode.id === 'month_list') { month_selector.value = this.innerHTML; document.getElementById('month_div').className = 'hidden_div'; } create_page(parseInt(year_selector.value), parseInt(month_selector.value)); } function popup_div(event) { var x = event.clientX - event.offsetX; var y = event.clientY - event.offsetY; var div; // TODO var width = 64; var height = 20; if (this.id === 'year_selector') { div = document.getElementById('year_div'); div_range.year.x_min = x; div_range.year.x_max = x + width; div_range.year.y_min = y; div_range.year.y_max = y + height; } else if (this.id === 'month_selector') { div = document.getElementById('month_div'); div_range.month.x_min = x; div_range.month.x_max = x + width; div_range.month.y_min = y; div_range.month.y_max = y + height; } /* else if (this.id === 'holiday_button') { div = document.getElementById('holiday_div'); div.style.width = '64px'; div.style.height = '100px'; div_range.holiday.x_min = x; div_range.holiday.x_max = x + width; div_range.holiday.y_min = y; div_range.holiday.y_max = y + height; }*/else { return; } if (div.className === 'hidden_div') { div.className = 'visible_div'; } else { div.className = 'hidden_div'; } div.style.left = x + 'px'; div.style.top = y + height + 'px'; } function update_right_pane(year, month, day) { var month_stuff = LunarCalendar.calendar(year, month, true); var general_datetime_list = document.getElementById('general_datetime_list'); var highlight_index = month_stuff['firstDay'] + day - 1; var lunar_month_name = month_stuff['monthData'][highlight_index]['lunarMonthName']; var lunar_day_name = month_stuff['monthData'][highlight_index]['lunarDayName']; var ganzhi_year = month_stuff['monthData'][highlight_index]['GanZhiYear']; var ganzhi_month = month_stuff['monthData'][highlight_index]['GanZhiMonth']; var ganzhi_day = month_stuff['monthData'][highlight_index]['GanZhiDay']; var zodiac = month_stuff['monthData'][highlight_index]['zodiac']; var weekday = weekdays[highlight_index % 7]; var month_str = month.toString(); if (month <= 9) { month_str = '0' + month; } var day_str = day.toString(); if (day <= 9) { day_str = '0' + day; } general_datetime_list.children[0].innerHTML = month_str + '-' + day_str + '-' + year + ' ' + weekday; general_datetime_list.children[1].innerHTML = day_str; // e.g. 06 general_datetime_list.children[2].innerHTML = ' '; general_datetime_list.children[3].innerHTML = ' '; general_datetime_list.children[4].innerHTML = ' '; //update_yiji_area(); month_stuff = null; } /* 节日查找从当月开始往后查找,包括公历节日、农历节日和农历节气,最多只查找到下一年 */ /*function go_to_holiday () { var year = today.getFullYear(); var month = today.getMonth() + 1; var day = 0; var month_stuff = LunarCalendar.calendar(year, month, false); var found = false; var target = this.innerHTML; do { for (var index = 0; index < month_stuff['monthDays']; index++) { if (target.indexOf(month_stuff['monthData'][index]['solarFestival']) >= 0 || target.indexOf(month_stuff['monthData'][index]['lunarFestival']) >= 0 || target.indexOf(month_stuff['monthData'][index]['term']) >= 0) { day = index + 1; found = true; break; } } if (found) { break; } if (month === 12) { year++; month = 1; } else { month++; } month_stuff = LunarCalendar.calendar(year, month, false); } while (year - today.getFullYear() <= 1); if (!found) { return; } year_selector.value = year; month_selector.value = month + 'Month'; highlight_day = day; create_page(year, month); month_stuff = null; }*/ ukui-panel-3.0.6.4/plugin-calendar/html/LunarCalendar-en.js0000644000175000017500000006127414204636772022063 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see 0 ? between : lunarYearDays.yearDays - Math.abs(between); var monthDays = lunarYearDays.monthDays; var tempDays = 0; var month = 0; for(var i=0;i end){ month = i; tempDays = tempDays-monthDays[i]; break; } } return [year,month,end - tempDays + 1]; }; /** * 根据距离正月初一的天数计算农历日期 * @param {Number} year 公历年,月,日 */ function getLunarByBetween(year,month,day){ var yearData = lunarInfo[year-minYear]; var zenMonth = yearData[1]; var zenDay = yearData[2]; var between = getDaysBetweenSolar(year,zenMonth-1,zenDay,year,month,day); if(between==0){ //正月初一 return [year,0,1]; }else{ var lunarYear = between>0 ? year : year-1; return getLunarDateByBetween(lunarYear,between); } }; /** * 两个公历日期之间的天数 */ function getDaysBetweenSolar(year,month,day,year1,month1,day1){ var date = new Date(year,month,day).getTime(); var date1 = new Date(year1,month1,day1).getTime(); return (date1-date) / 86400000; }; /** * 计算农历日期离正月初一有多少天 * @param {Number} year,month,day 农年,月(0-12,有闰月),日 */ function getDaysBetweenZheng(year,month,day){ var lunarYearDays = getLunarYearDays(year); var monthDays = lunarYearDays.monthDays; var days = 0; for(var i=0;i maxYear)return {error:100, msg:errorCode[100]}; return { year : year, month : month, day : day }; }; /** * 将农历转换为公历 * @param {Number} year,month,day 农历年,月(1-13,有闰月),日 */ function lunarToSolar(_year,_month,_day){ var inputDate = formateDate(_year,_month,_day); if(inputDate.error)return inputDate; var year = inputDate.year; var month = inputDate.month; var day = inputDate.day; var between = getDaysBetweenZheng(year,month,day); //离正月初一的天数 var yearData = lunarInfo[year-minYear]; var zenMonth = yearData[1]; var zenDay = yearData[2]; var offDate = new Date(year,zenMonth-1,zenDay).getTime() + between * 86400000; offDate = new Date(offDate); return { year : offDate.getFullYear(), month : offDate.getMonth()+1, day : offDate.getDate() }; }; /** * 将公历转换为农历 * @param {Number} year,month,day 公历年,月,日 */ function solarToLunar(_year,_month,_day){ var inputDate = formateDate(_year,_month,_day,minYear); if(inputDate.error)return inputDate; var year = inputDate.year; var month = inputDate.month; var day = inputDate.day; cacheUtil.setCurrent(year); //立春日期 var term2 = cacheUtil.get('term2') ? cacheUtil.get('term2') : cacheUtil.set('term2',getTerm(year,2)); //二十四节气 var termList = cacheUtil.get('termList') ? cacheUtil.get('termList') : cacheUtil.set('termList',getYearTerm(year)); var firstTerm = getTerm(year,month*2); //某月第一个节气开始日期 var GanZhiYear = (month>1 || month==1 && day>=term2) ? year+1 : year;//干支所在年份 var GanZhiMonth = day>=firstTerm ? month+1 : month; //干支所在月份(以节气为界) var lunarDate = getLunarByBetween(year,month,day); var lunarLeapMonth = getLunarLeapYear(lunarDate[0]); var lunarMonthName = ''; if(lunarLeapMonth>0 && lunarLeapMonth==lunarDate[1]){ lunarMonthName = '闰'+DATA.monthCn[lunarDate[1]-1]+'月'; }else if(lunarLeapMonth>0 && lunarDate[1]>lunarLeapMonth){ lunarMonthName = DATA.monthCn[lunarDate[1]-1]+'月'; }else{ lunarMonthName = DATA.monthCn[lunarDate[1]]+'月'; } //农历节日判断 var lunarFtv = ''; var lunarMonthDays = getLunarYearDays(lunarDate[0]).monthDays; //除夕 if(lunarDate[1] == lunarMonthDays.length-1 && lunarDate[2]==lunarMonthDays[lunarMonthDays.length-1]){ lunarFtv = lunarFestival['d0100']; }else if(lunarLeapMonth>0 && lunarDate[1]>lunarLeapMonth){ lunarFtv = lunarFestival[formateDayD4(lunarDate[1]-1,lunarDate[2])]; }else{ lunarFtv = lunarFestival[formateDayD4(lunarDate[1],lunarDate[2])]; } var res = { zodiac : getYearZodiac(GanZhiYear), GanZhiYear : getLunarYearName(GanZhiYear), GanZhiMonth : getLunarMonthName(year,GanZhiMonth), GanZhiDay : getLunarDayName(year,month,day), //放假安排:0无特殊安排,1工作,2放假 worktime : worktime['y'+year] && worktime['y'+year][formateDayD4(month,day)] ? worktime['y'+year][formateDayD4(month,day)] : 0, term : termList[formateDayD4(month,day)], lunarYear : lunarDate[0], lunarMonth : lunarDate[1]+1, lunarDay : lunarDate[2], lunarMonthName : lunarMonthName, lunarDayName : DATA.dateCn[lunarDate[2]-1], lunarLeapMonth : lunarLeapMonth, solarFestival : solarFestival[formateDayD4(month,day)], lunarFestival : lunarFtv }; return res; }; /** * 获取指定公历月份的农历数据 * return res{Object} * @param {Number} year,month 公历年,月 * @param {Boolean} fill 是否用上下月数据补齐首尾空缺,首例数据从周日开始 */ function calendar(_year,_month,fill){ var inputDate = formateDate(_year,_month); if(inputDate.error)return inputDate; var year = inputDate.year; var month = inputDate.month; var calendarData = solarCalendar(year,month+1,fill); for(var i=0;i 0){ //前补 var preYear = month-1<0 ? year-1 : year; var preMonth = month-1<0 ? 11 : month-1; preMonthDays = getSolarMonthDays(preYear,preMonth); preMonthData = creatLenArr(preYear,preMonth+1,res.firstDay,preMonthDays-res.firstDay+1); res.monthData = preMonthData.concat(res.monthData); } if(7*6 - res.monthData.length!=0){ //后补 var nextYear = month+1>11 ? year+1 : year; var nextMonth = month+1>11 ? 0 : month+1; var fillLen = 7*6 - res.monthData.length; nextMonthData = creatLenArr(nextYear,nextMonth+1,fillLen,1); res.monthData = res.monthData.concat(nextMonthData); } } return res; }; /** * 设置放假安排【对外暴露接口】 * @param {Object} workData */ function setWorktime(workData){ extend(worktime,workData); }; var LunarCalendar = { solarToLunar : solarToLunar, lunarToSolar : lunarToSolar, calendar : calendar, solarCalendar : solarCalendar, setWorktime : setWorktime, getSolarMonthDays : getSolarMonthDays }; if (typeof define === 'function'){ define (function (){ return LunarCalendar; }); }else if(typeof exports === 'object'){ module.exports = LunarCalendar; }else{ window.LunarCalendar = LunarCalendar; }; })(); ukui-panel-3.0.6.4/plugin-calendar/html/LunarCalendar.js0000644000175000017500000006732414204636772021465 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see 0 ? between : lunarYearDays.yearDays - Math.abs(between); var monthDays = lunarYearDays.monthDays; var tempDays = 0; var month = 0; var lunarName = 0; end = Math.round(end); for(var i=0;i end){ month = i; tempDays = tempDays-monthDays[i]; break; } } lunarName = Math.round(end - tempDays + 1); return [year,month,lunarName]; // return [year,month,end - tempDays + 1]; }; /** * 根据距离正月初一的天数计算农历日期 * @param {Number} year 公历年,月,日 */ function getLunarByBetween(year,month,day){ var yearData = lunarInfo[year-minYear]; var zenMonth = yearData[1]; var zenDay = yearData[2]; var between = getDaysBetweenSolar(year,zenMonth-1,zenDay,year,month,day); if(between==0){ //正月初一 return [year,0,1]; }else{ var lunarYear = between>0 ? year : year-1; return getLunarDateByBetween(lunarYear,between); } }; /** * 两个公历日期之间的天数 */ function getDaysBetweenSolar(year,month,day,year1,month1,day1){ var date = new Date(year,month,day).getTime(); var date1 = new Date(year1,month1,day1).getTime(); return (date1-date) / 86400000; }; /** * 计算农历日期离正月初一有多少天 * @param {Number} year,month,day 农年,月(0-12,有闰月),日 */ function getDaysBetweenZheng(year,month,day){ var lunarYearDays = getLunarYearDays(year); var monthDays = lunarYearDays.monthDays; var days = 0; for(var i=0;i maxYear)return {error:100, msg:errorCode[100]}; return { year : year, month : month, day : day }; }; /** * 将农历转换为公历 * @param {Number} year,month,day 农历年,月(1-13,有闰月),日 */ function lunarToSolar(_year,_month,_day){ var inputDate = formateDate(_year,_month,_day); if(inputDate.error)return inputDate; var year = inputDate.year; var month = inputDate.month; var day = inputDate.day; var between = getDaysBetweenZheng(year,month,day); //离正月初一的天数 var yearData = lunarInfo[year-minYear]; var zenMonth = yearData[1]; var zenDay = yearData[2]; var offDate = new Date(year,zenMonth-1,zenDay).getTime() + between * 86400000; offDate = new Date(offDate); return { year : offDate.getFullYear(), month : offDate.getMonth()+1, day : offDate.getDate() }; }; /** * 将公历转换为农历 * @param {Number} year,month,day 公历年,月,日 */ function solarToLunar(_year,_month,_day){ var inputDate = formateDate(_year,_month,_day,minYear); if(inputDate.error)return inputDate; var year = inputDate.year; var month = inputDate.month; var day = inputDate.day; cacheUtil.setCurrent(year); //立春日期 var term2 = cacheUtil.get('term2') ? cacheUtil.get('term2') : cacheUtil.set('term2',getTerm(year,2)); //二十四节气 var termList = cacheUtil.get('termList') ? cacheUtil.get('termList') : cacheUtil.set('termList',getYearTerm(year)); var firstTerm = getTerm(year,month*2); //某月第一个节气开始日期 var GanZhiYear = (month>1 || month==1 && day>=term2) ? year+1 : year;//干支所在年份 var GanZhiMonth = day>=firstTerm ? month+1 : month; //干支所在月份(以节气为界) var lunarDate = getLunarByBetween(year,month,day); var lunarLeapMonth = getLunarLeapYear(lunarDate[0]); var lunarMonthName = ''; if(lunarLeapMonth>0 && lunarLeapMonth==lunarDate[1]){ lunarMonthName = '闰'+DATA.monthCn[lunarDate[1]-1]+'月'; }else if(lunarLeapMonth>0 && lunarDate[1]>lunarLeapMonth){ lunarMonthName = DATA.monthCn[lunarDate[1]-1]+'月'; }else{ lunarMonthName = DATA.monthCn[lunarDate[1]]+'月'; } //农历节日判断 var lunarFtv = ''; var lunarMonthDays = getLunarYearDays(lunarDate[0]).monthDays; //除夕 if(lunarDate[1] == lunarMonthDays.length-1 && lunarDate[2]==lunarMonthDays[lunarMonthDays.length-1]){ lunarFtv = lunarFestival['d0100']; }else if(lunarLeapMonth>0 && lunarDate[1]>=lunarLeapMonth){ lunarFtv = lunarFestival[formateDayD4(lunarDate[1]-1,lunarDate[2])]; }else{ lunarFtv = lunarFestival[formateDayD4(lunarDate[1],lunarDate[2])]; } var res = { zodiac : getYearZodiac(GanZhiYear), GanZhiYear : getLunarYearName(GanZhiYear), GanZhiMonth : getLunarMonthName(year,GanZhiMonth), GanZhiDay : getLunarDayName(year,month,day), //放假安排:0无特殊安排,1工作,2放假 worktime : worktime['y'+year] && worktime['y'+year][formateDayD4(month,day)] ? worktime['y'+year][formateDayD4(month,day)] : 0, term : termList[formateDayD4(month,day)], lunarYear : lunarDate[0], lunarMonth : lunarDate[1]+1, lunarDay : lunarDate[2], lunarMonthName : lunarMonthName, lunarDayName : DATA.dateCn[lunarDate[2]-1], lunarLeapMonth : lunarLeapMonth, solarFestival : solarFestival[formateDayD4(month,day)], lunarFestival : lunarFtv }; return res; }; /** * 获取指定公历月份的农历数据 * return res{Object} * @param {Number} year,month 公历年,月 * @param {Boolean} fill 是否用上下月数据补齐首尾空缺,首例数据从周日开始 */ function calendar(_year,_month,fill,mode){ var inputDate = formateDate(_year,_month); if(inputDate.error)return inputDate; var year = inputDate.year; var month = inputDate.month; var calendarData = solarCalendar(year,month+1,fill,mode); for(var i=0;i 0)//每周从周一开始,一号是星期一至星期六,补 n-1天 { preMonthData = creatLenArr(preYear,preMonth+1,res.firstDay -1 ,preMonthDays-(res.firstDay-1)+1); } else//每周从周一开始,一号是星期一至星期六 补6天 { preMonthData = creatLenArr(preYear,preMonth+1,res.firstDay + 6 ,preMonthDays-(res.firstDay + 6)+1); } } res.monthData = preMonthData.concat(res.monthData); } if(7*6 - res.monthData.length!=0){ //后补 var nextYear = month+1>11 ? year+1 : year; var nextMonth = month+1>11 ? 0 : month+1; var fillLen = 7*6 - res.monthData.length; nextMonthData = creatLenArr(nextYear,nextMonth+1,fillLen,1); res.monthData = res.monthData.concat(nextMonthData); } } return res; }; /** * 设置放假安排【对外暴露接口】 * @param {Object} workData */ function setWorktime(workData){ extend(worktime,workData); }; var LunarCalendar = { solarToLunar : solarToLunar, lunarToSolar : lunarToSolar, calendar : calendar, solarCalendar : solarCalendar, setWorktime : setWorktime, getSolarMonthDays : getSolarMonthDays }; if (typeof define === 'function'){ define (function (){ return LunarCalendar; }); }else if(typeof exports === 'object'){ module.exports = LunarCalendar; }else{ window.LunarCalendar = LunarCalendar; }; })(); ukui-panel-3.0.6.4/plugin-calendar/html/arm64-en.html0000644000175000017500000000564514204636772020631 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see
  1. 2015-02-04 星期三
  2. 4
  3. 十一月十四
  4. 甲午年【马年】
  5. 丙子月 庚辰日
ukui-panel-3.0.6.4/plugin-calendar/html/arm64-en.css0000644000175000017500000001210514204636772020442 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see
lun mar mer jeu ven sam dim
  1. 2015-02-04 星期三
  2. 4
  3. 十一月十四
  4. 甲午年【马年】
  5. 丙子月 庚辰日
ukui-panel-3.0.6.4/plugin-calendar/html/index-solar-cn.js0000644000175000017500000010725714204636772021575 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see 0) { scrollUp_count--; } else { scrollUp_count = 2; } } for(var index = 0; index <16; index++) { // li.children[0].children[index].innerHTML = '
'; //li.children[0].children[index].innerHTML = '
'+ list[index]+ '月'; li.children[0].children[index].innerHTML =''+ list[index]+ '月' + ''; // li.children[0].children[index].innerHTML = list[index]+ '月'; // document.getElementsByTagName('span').style="float:left;width:250px;background:#6C3;"; if(index >= bind_click_position) { if(scrollUp_count%3 ===2) { if(bind_click_count < 8) { li.children[0].children[index].style.color = "#FFFFFFFF"; li.children[0].children[index].addEventListener('click', new_month_selected); bind_click_count = bind_click_count + 1; } else { li.children[0].children[index].style.color = "#FFFFFF33"; li.children[0].children[index].addEventListener('click', new_month_selected_add); } continue; } if(bind_click_count < 12) // max bind _count of month click is no more than 12 { li.children[0].children[index].style.color = "#FFFFFFFF"; li.children[0].children[index].addEventListener('click', new_month_selected); bind_click_count = bind_click_count + 1; } else { li.children[0].children[index].style.color = "#FFFFFF33"; li.children[0].children[index].addEventListener('click', new_month_selected_add); } } else { li.children[0].children[index].style.color = "#FFFFFF33"; li.children[0].children[index].addEventListener('click', new_month_selected_minus); } } } function new_month_selected_add() { if (this.parentNode.className=== 'show_months') { var str = this.innerHTML.replace("",""); month_selector.value = str.replace("",""); document.getElementById('month_div').className = 'hidden_div'; calendar.style.display = ""; year = parseInt(year_selector.value); year++; year_selector.value = year + '年'; selected_date_div.innerHTML = year_selector.value + month_selector.value; create_page(parseInt(year_selector.value), parseInt(month_selector.value)); year--; } } function new_month_selected_minus() { if (this.parentNode.className=== 'show_months') { var str = this.innerHTML.replace("",""); month_selector.value = str.replace("",""); document.getElementById('month_div').className = 'hidden_div'; calendar.style.display = ""; year = parseInt(year_selector.value); year--; year_selector.value = year + '年'; selected_date_div.innerHTML = year_selector.value + month_selector.value; create_page(parseInt(year_selector.value), parseInt(month_selector.value)); year++; } } function update_year_month_ui() { var li = document.getElementById('year_div'); for (var index = 0; index < 16; index++) { // li.children[0].children[index].innerHTML = '
'; var curretYear = year + index; li.children[0].children[index].innerHTML= ''+curretYear+ '年' +'' ; //li.children[0].children[index].innerHTML= '
'+curretYear+ '年'; // if(index === 0) // { // li.children[0].children[index].style.backgroundColor = "#2b87a8"; // } li.children[0].children[index].addEventListener('click', new_month_selected); // new year implies new month // year_list.appendChild(li); // if (index === year) { // year_selector.value = index + '年'; // } } li = document.getElementById('month_div'); for (var index = 0; index < 16; index++) { li.children[0].children[index].removeEventListener('click', new_month_selected); li.children[0].children[index].style.color = "#FFFFFFFF"; if(index >=12) { var newIndex = index -12 + 1; li.children[0].children[index].style.color = "#FFFFFF33"; //li.children[0].children[index].innerHTML = '
' + new_index + '月'; li.children[0].children[index].innerHTML= ''+newIndex + '月' +'' ; //li.children[0].children[index].innerHTML = "1月"; } else { var newIndex = index + 1; //li.children[0].children[index].innerHTML ='
' + newIndex+ '月'; li.children[0].children[index].innerHTML =''+ newIndex+ '月' + '' ; } if(index < 12) { li.children[0].children[index].addEventListener('click', new_month_selected); } else { li.children[0].children[index].addEventListener('click', new_month_selected_add); } // month_list.appendChild(li); if (index === month + 1) { month_selector.value = index + '月'; } } } function updateUi() { year_selector.value = year + '年'; update_year_month_ui(); // var li = document.getElementById('year_div'); // for (var index = 0; index < 16; index++) { // li.children[0].children[index].innerHTML= year + index + '年'; // li.children[0].children[index].addEventListener('click', new_month_selected); // new year implies new month // // year_list.appendChild(li); // // if (index === year) { // // year_selector.value = index + '年'; // // } // } // li = document.getElementById('month_div'); // for (var index = 0; index < 16; index++) { // if(index >=12) // { // var new_index = index -12; // li.children[0].children[index].innerHTML = new_index +1+ '月'; // } // else // { // li.children[0].children[index].innerHTML = index +1+ '月'; // } // li.children[0].children[index].addEventListener('click', new_month_selected); // // month_list.appendChild(li); // if (index === month + 1) { // month_selector.value = index + '月'; // } // } } function scroll_div(event) { var e = event||window.event; if(e.wheelDelta > 0) { if(this.id === 'year_div') { year = year - 4; } else if(this.id === 'month_div') { scrollUp_count++; update_month_ui(0); return; } } else { if(this.id === 'year_div') { year = year + 4; } else if(this.id === 'month_div') { scrollDown_count++; update_month_ui(1); return; } } updateUi(); } function update_yiji_area() { "use strict"; var year = parseInt(year_selector.value, 10); var month = parseInt(month_selector.value, 10); var hl_table = document.getElementById('hl_table'); var current_row; var current_cell; if (year !== parseInt(hl_script.id, 10)) { load_hl_script(year); return; } if (typeof HuangLi['y' + year] === 'undefined') { for (var row = 0; row < 2; row++) { if (hl_table.rows.length === row) { current_row = hl_table.insertRow(row); } else { current_row = hl_table.rows[row]; } for (var column = 1; column < 5; column++) { if (current_row.cells.length === column) { current_cell = current_row.insertCell(column); } else { current_cell = current_row.cells[column]; } if (row === 1) { current_cell.innerHTML = '无数据'; } else { current_cell.innerHTML = ''; } } } } var day = highlight_day; var month_str = month.toString(); var day_str = day.toString(); if (month <= 9) { month_str = '0' + month; } if (day <= 9) { day_str = '0' + day; } var yi_str = HuangLi['y' + year]['d' + month_str + day_str]['y']; var ji_str = HuangLi['y' + year]['d' + month_str + day_str]['j']; var hl_yi_data = yi_str.split('.'); var hl_ji_data = ji_str.split('.'); for (var row = 0; row < 2; row++) { if (hl_table.rows.length === row) { current_row = hl_table.insertRow(row); } else { current_row = hl_table.rows[row]; } for (var column = 1; column < 5; column++) { if (current_row.cells.length === column) { current_cell = current_row.insertCell(column); } else { current_cell = current_row.cells[column]; } if(0 == row ) { if(hl_yi_data[column-1]) { current_cell.innerHTML = hl_yi_data[column-1]; } else { current_cell.innerHTML = ''; } } else { if(hl_ji_data[column-1]) { current_cell.innerHTML = hl_ji_data[column-1]; } else { current_cell.innerHTML =''; } } } } } function load_hl_script(year) { "use strict"; if (hl_script) { document.body.removeChild(hl_script); hl_script = null; } hl_script = document.createElement("SCRIPT"); hl_script.type = "text/javascript"; hl_script.src = "hl/hl" + year + '.js'; hl_script.id = year; hl_script.onload = function() { update_yiji_area(); }; document.body.appendChild(hl_script); } window.onload = function () { "use strict"; load_hl_script(today.getFullYear()); // var year_list = document.getElementById('year_list'); // var month_list = document.getElementById('month_list'); year = today.getFullYear(); month = today.getMonth(); var real_month = month + 1; selected_date_div = document.getElementById('selected_date_div'); year_selector = document.createElement('year_selector'); month_selector = document.createElement('month_selector'); year_selector.value = year + '年'; month_selector.value = real_month +'月'; selected_date_div.innerHTML = year_selector.value + month_selector.value; // year_selector = document.getElementById('year_selector'); // // year_selector.addEventListener('click', popup_div); // month_selector = document.getElementById('month_selector'); // month_selector.addEventListener('click', popup_div); //end // alert("begin"); year_button = document.getElementById('year_button'); year_button.addEventListener('click', popup_div); // alert("end"); month_button= document.getElementById('month_button'); month_button.addEventListener('click', popup_div); document.getElementById('year_div').addEventListener('mousewheel',scroll_div); document.getElementById('month_div').addEventListener('mousewheel',scroll_div); document.addEventListener('click', function(event) { }); updateUi(); var goto_arrows = document.getElementsByTagName('input'); var n_months = (year_range['high'] - year_range['low'] + 1) * 12; for (var index = 0; index < goto_arrows.length; index++) { goto_arrows[index].addEventListener('click', function() { var year = parseInt(year_selector.value); var month = parseInt(month_selector.value); if(PrevClick != null) { PrevClick.style.border = "none"; PrevClick = null; } //page the year ui if(document.getElementById('year_div').className ==='visible_div') { var li = document.getElementById('year_div'); if(this.id === 'go_prev_month') { year = year -16; year_selector.value = year + '年'; // selected_date_div.innerHTML = year_selector.value + month_selector.value; for (var index = 0; index < 16; index++) { // li.children[0].children[index].innerHTML = '
'; var currentYear = year + index; //li.children[0].children[index].innerHTML= '
' + curretYear + '年'; li.children[0].children[index].innerHTML =''+ currentYear+ '年' + ''; li.children[0].children[index].addEventListener('click', new_month_selected); // new year implies new month } } else if(this.id === 'go_next_month') { year = year + 16; year_selector.value = year + '年'; // selected_date_div.innerHTML = year_selector.value + month_selector.value; for (var index = 0; index < 16; index++) { // li.children[0].children[index].innerHTML = '
'; var currentYear = year + index; //li.children[0].children[index].innerHTML= '
'+ curretYear + '年'; li.children[0].children[index].innerHTML =''+ currentYear+ '年' + ''; li.children[0].children[index].addEventListener('click', new_month_selected); // new year implies new month } } return; } else if(document.getElementById('month_div').className ==='visible_div')//page the month ui { if(this.id === 'go_prev_month') { year --; year_selector.value = year + '年'; selected_date_div.innerHTML = year_selector.value + month_selector.value; } else if(this.id === 'go_next_month') { year++; year_selector.value = year + '年'; selected_date_div.innerHTML = year_selector.value + month_selector.value; } return; } // var year = parseInt(year_selector.value); // var month = parseInt(month_selector.value); var month_offset = (year - year_range['low']) * 12 + month - 1; // [0, n_months - 1] if (this.id === 'go_prev_year') { month_offset -= 12; } else if (this.id === 'go_next_year') { month_offset += 12; } else if (this.id === 'go_prev_month') { month_offset -= 1; } else if (this.id === 'go_next_month') { month_offset += 1; } else { return; } if (month_offset < 0 || month_offset > n_months - 1) { return; } year_selector.value = Math.floor(month_offset / 12) + year_range['low'] + '年'; month_selector.value = month_offset % 12 === 0 ? 1 +'月': month_offset % 12 + 1 + '月'; selected_date_div.innerHTML = year_selector.value + month_selector.value; create_page(parseInt(year_selector.value), parseInt(month_selector.value)); }); } var holidays = ['元旦节', '春节', '清明节', '劳动节', '端午节', '中秋节', '国庆节']; var holiday_list = document.getElementById('holiday_list'); for (var index = 0; index < holidays.length; index++) { var li = document.createElement('LI'); li.innerHTML = holidays[index]; li.addEventListener('click', go_to_holiday); holiday_list.appendChild(li); } //var holiday_button = document.getElementById('holiday_button'); //holiday_button.addEventListener('click', popup_div); var today_button = document.getElementById('today_button'); today_button.addEventListener('click', function() { year_selector.value = today.getFullYear() + '年'; month_selector.value = today.getMonth() + 1 + '月'; selected_date_div.innerHTML = year_selector.value + month_selector.value; highlight_day = today.getDate(); convertToNormal(); year = today.getFullYear(); month = today.getMonth(); if(PrevClick != null) { PrevClick.style.border = "none"; PrevClick = null; } create_page(today.getFullYear(), today.getMonth() + 1); update_year_month_ui(); var header_id=document.getElementById("header"); var header_color=header_id.style.background; var x=document.getElementsByClassName("day_today"); var i; if (header_color == "rgb(0, 0, 0)"){ for (i = 0; i < x.length; i++) { x[i].style.backgroundColor = "#3593b5"; } } else{ for (i = 0; i < x.length; i++) { x[i].style.backgroundColor = header_color; } } }); calendar = document.getElementById('calendar_table'); create_page(parseInt(year_selector.value), parseInt(month_selector.value)); } function create_page(year, month) { if (year < year_range['low'] || year > year_range['high']) return; var month_stuff = LunarCalendar.calendar(year, month, true,0); highlight_day = highlight_day > month_stuff['monthDays'] ? month_stuff['monthDays'] : highlight_day; var current_row = null; var current_cell = null; for (var row = 1; row < 7; row++) { if (calendar.rows.length === row) { current_row = calendar.insertRow(row); } else { current_row = calendar.rows[row]; } for (var column = 0; column < 7; column++) { if (current_row.cells.length === column) { current_cell = current_row.insertCell(column); current_cell.addEventListener('click', function() { highlight_day = parseInt(this.children[0].innerHTML); if(PrevClick != null) { PrevClick.style.border = "none"; } this.style.border = "1px solid #7eb4ea"; PrevClick = this; if (this.className === 'day_other_month') { return; } create_page(parseInt(year_selector.value), parseInt(month_selector.value)); }); } else { current_cell = current_row.cells[column]; } var index = (row - 1) * 7 + column; // [0, 7 * 6 - 1] /* * 注意判断顺序 * 1. 表格开头/结尾的非本月日期的单元格样式与其他单元格无关,需要最先判断 * 2. 其次是‘今天’的单元格样式 * 3. 再次是当前鼠标点击选中的单元格 * 4. 再次是属于周末的单元格 * 5. 最后是其他普通单元格 */ if (index < month_stuff['firstDay'] || index >= month_stuff['firstDay'] + month_stuff['monthDays']) { current_cell.className = 'day_other_month'; } else if (today.getDate() === month_stuff['monthData'][index]['day'] && today.getMonth() === month - 1 && today.getFullYear() === year) { current_cell.className = 'day_today'; } else if (index === highlight_day + month_stuff['firstDay'] - 1) { current_cell.className = 'day_highlight'; } else if (column === 0 || column === 6) { current_cell.className = 'day_weekend'; } else { current_cell.className = 'day_this_month'; } var lunar_day; if (month_stuff['monthData'][index]['lunarFestival']) { lunar_day = month_stuff['monthData'][index]['lunarFestival']; // } else if (month_stuff['monthData'][index]['solarFestival']) { // lunar_day = month_stuff['monthData'][index]['solarFestival']; } else { lunar_day = month_stuff['monthData'][index]['lunarDayName']; } var worktime = null; if (month_stuff['monthData'][index]['worktime'] === 2) { worktime = document.createElement("SPAN"); worktime.className = 'worktime2'; worktime.innerHTML = '休'; } else if (month_stuff['monthData'][index]['worktime'] === 1) { worktime = document.createElement("SPAN"); worktime.className = 'worktime1'; worktime.innerHTML = '班'; } else { } current_cell.innerHTML = '' + month_stuff['monthData'][index]['day'] + '' // if (worktime && current_cell.className !== 'day_other_month') { // current_cell.appendChild(worktime); // } if (worktime) { current_cell.appendChild(worktime); } // if (month_stuff['monthData'][index]['worktime'] === 2) { // worktime = document.createElement("SPAN"); // worktime.className = 'worktime2'; // worktime.innerHTML = ' '; // } else if (month_stuff['monthData'][index]['worktime'] === 1) { // worktime = document.createElement("SPAN"); // worktime.className = 'worktime1'; // worktime.innerHTML = ' '; // } else { // } // if (worktime && current_cell.className !== 'day_other_month') { // current_cell.innerHTML = worktime.innerHTML+ // ' ' + // month_stuff['monthData'][index]['day'] + // '' + // '
' + // '' + // lunar_day + // ''; // } // else // { // current_cell.innerHTML = '' + // month_stuff['monthData'][index]['day'] + // '' + // '
' + // '' + // lunar_day + // ''; // } } } update_right_pane(year, month, highlight_day); month_stuff = null; if (header_color == "rgb(0, 0, 0)"){ var day_this_month_len=document.getElementsByClassName('day_this_month').length; for (var i=0; i",""); year_selector.value = str.replace("",""); document.getElementById('year_div').className = 'hidden_div'; calendar.style.display = ""; } else if (this.parentNode.className=== 'show_months') { var str = this.innerHTML.replace("",""); month_selector.value = str.replace("",""); document.getElementById('month_div').className = 'hidden_div'; calendar.style.display = ""; } selected_date_div.innerHTML = year_selector.value + month_selector.value; create_page(parseInt(year_selector.value), parseInt(month_selector.value)); } function popup_div(event) { var x = event.clientX - event.offsetX; var y = event.clientY - event.offsetY; var div; // TODO var width = 64; var height = 20; if (this.id === 'year_button') { div = document.getElementById('year_div'); div_range.year.x_min = x; div_range.year.x_max = x + width; div_range.year.y_min = y; div_range.year.y_max = y + height; if (div.className === 'hidden_div') { div.className = 'visible_div'; document.getElementById('month_div').className = 'hidden_div'; calendar.style.display = "none"; year = parseInt(year_selector.value); var li = document.getElementById('year_div'); year_selector.value = year + '年'; // selected_date_div.innerHTML = year_selector.value + month_selector.value; for (var index = 0; index < 16; index++) { // li.children[0].children[index].innerHTML = '
'; var currentYear = year + index; //li.children[0].children[index].innerHTML= '
' + curretYear + '年'; li.children[0].children[index].innerHTML =''+ currentYear+ '年' + ''; li.children[0].children[index].addEventListener('click', new_month_selected); // new year implies new month } } else { div.className = 'hidden_div'; calendar.style.display = ""; } } else if (this.id === 'month_button') { div = document.getElementById('month_div'); div_range.month.x_min = x; div_range.month.x_max = x + width; div_range.month.y_min = y; div_range.month.y_max = y + height; if (div.className === 'hidden_div') { div.className = 'visible_div'; document.getElementById('year_div').className = 'hidden_div'; calendar.style.display = "none"; } else { div.className = 'hidden_div'; calendar.style.display = ""; } } else { return; } // if (div.className === 'hidden_div') { // div.className = 'visible_div'; // calendar.style.display = "none"; // } else { // div.className = 'hidden_div'; // calendar.style.display = ""; // } div.style.left = x + 'px'; div.style.top = y + height + 'px'; update_year_month_ui(); //updateUi(); } function update_right_pane(year, month, day) { var month_stuff = LunarCalendar.calendar(year, month, true, 0); var general_datetime_list = document.getElementById('general_datetime_list'); var datetime_container = document.getElementById('datetime_container'); var highlight_index = month_stuff['firstDay'] + day - 1; var lunar_month_name = month_stuff['monthData'][highlight_index]['lunarMonthName']; var lunar_day_name = month_stuff['monthData'][highlight_index]['lunarDayName']; var ganzhi_year = month_stuff['monthData'][highlight_index]['GanZhiYear']; var ganzhi_month = month_stuff['monthData'][highlight_index]['GanZhiMonth']; var ganzhi_day = month_stuff['monthData'][highlight_index]['GanZhiDay']; var zodiac = month_stuff['monthData'][highlight_index]['zodiac']; var weekday = weekdays[highlight_index % 7]; var month_str = month.toString(); if (month <= 9) { month_str = '0' + month; } var day_str = day.toString(); if (day <= 9) { day_str = '0' + day; } if(NeedChangeCurrentTime) { datetime_container.children[1].innerHTML = year + '-' + month_str + '-' + day_str + ' 星期' + weekday /* + ' '+lunar_month_name + lunar_day_name*/; NeedChangeCurrentTime = 0; } /* general_datetime_list.children[0].innerHTML = year + '-' + month_str + '-' + day_str + ' 星期' + weekday; general_datetime_list.children[1].innerHTML = day_str; // e.g. 06 general_datetime_list.children[2].innerHTML = lunar_month_name + lunar_day_name;*/ //general_datetime_list.children[0].innerHTML = ganzhi_year + '年' + '【' + zodiac + '年' + '】' + ganzhi_month + '月 ' + ganzhi_day + '日'; // general_datetime_list.children[1].innerHTML = ganzhi_month + '月 ' + ganzhi_day + '日'; updateTime(); update_yiji_area(); month_stuff = null; } /* 节日查找从当月开始往后查找,包括公历节日、农历节日和农历节气,最多只查找到下一年 */ function go_to_holiday () { var year = today.getFullYear(); var month = today.getMonth() + 1; var day = 0; var month_stuff = LunarCalendar.calendar(year, month, false, 0); var found = false; var target = this.innerHTML; do { for (var index = 0; index < month_stuff['monthDays']; index++) { if (target.indexOf(month_stuff['monthData'][index]['solarFestival']) >= 0 || target.indexOf(month_stuff['monthData'][index]['lunarFestival']) >= 0 || target.indexOf(month_stuff['monthData'][index]['term']) >= 0) { day = index + 1; found = true; break; } } if (found) { break; } if (month === 12) { year++; month = 1; } else { month++; } month_stuff = LunarCalendar.calendar(year, month, false, 0); } while (year - today.getFullYear() <= 1); if (!found) { return; } year_selector.value = year + '年'; month_selector.value = month + '月'; highlight_day = day; create_page(year, month); month_stuff = null; } ukui-panel-3.0.6.4/plugin-calendar/html/ukui-es.html0000644000175000017500000000560114204636772020652 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see
DOM LUN MAR MIE JUE VIE SAB
  1. 2015-02-04 星期三
  2. 4
  3. 十一月十四
  4. 甲午年【马年】
  5. 丙子月 庚辰日
ukui-panel-3.0.6.4/plugin-calendar/html/index-ru.js0000644000175000017500000004137014204636772020476 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see div_range.year.x_max || x < div_range.year.x_min || y > div_range.year.y_max || y < div_range.year.y_min) { year_div.className = 'hidden_div'; } } if (month_div.className === 'visible_div') { if (x > div_range.month.x_max || x < div_range.month.x_min || y > div_range.month.y_max || y < div_range.month.y_min ) { month_div.className = 'hidden_div'; } } /* if (holiday_div.className === 'visible_div') { if (x > div_range.holiday.x_max || x < div_range.holiday.x_min || y > div_range.holiday.y_max || y < div_range.holiday.y_min ) { holiday_div.className = 'hidden_div'; } }*/ }); for (var index = year_range['low']; index <= year_range['high']; index++) { var li = document.createElement('LI'); li.innerHTML = index; li.addEventListener('click', new_month_selected); // new year implies new month year_list.appendChild(li); if (index === year) { year_selector.value = index; } } for (var index = 1; index <= 12; index++) { var li = document.createElement('LI'); li.innerHTML = index; li.addEventListener('click', new_month_selected); month_list.appendChild(li); if (index === month + 1) { month_selector.value = index; } } var goto_arrows = document.getElementsByTagName('input'); var n_months = (year_range['high'] - year_range['low'] + 1) * 12; for (var index = 0; index < goto_arrows.length; index++) { goto_arrows[index].addEventListener('click', function() { var year = parseInt(year_selector.value); var month = parseInt(month_selector.value); var month_offset = (year - year_range['low']) * 12 + month - 1; // [0, n_months - 1] if (this.id === 'go_prev_year') { month_offset -= 12; } else if (this.id === 'go_next_year') { month_offset += 12; } else if (this.id === 'go_prev_month') { month_offset -= 1; } else if (this.id === 'go_next_month') { month_offset += 1; } else { return; } if (month_offset < 0 || month_offset > n_months - 1) { return; } year_selector.value = Math.floor(month_offset / 12) + year_range['low']; month_selector.value = month_offset % 12 === 0 ? 1 : month_offset % 12 + 1; create_page(parseInt(year_selector.value), parseInt(month_selector.value)); }); } /* var holidays = ['元旦节', '春节', '清明节', '劳动节', '端午节', '中秋节', '国庆节']; var holiday_list = document.getElementById('holiday_list'); for (var index = 0; index < holidays.length; index++) { var li = document.createElement('LI'); li.innerHTML = holidays[index]; li.addEventListener('click', go_to_holiday); holiday_list.appendChild(li); }*/ // var holiday_button = document.getElementById('holiday_button'); // holiday_button.addEventListener('click', popup_div); var today_button = document.getElementById('today_button'); today_button.addEventListener('click', function() { year_selector.value = today.getFullYear(); month_selector.value = today.getMonth() + 1; highlight_day = today.getDate(); create_page(today.getFullYear(), today.getMonth() + 1); }); calendar = document.getElementById('calendar_table'); create_page(parseInt(year_selector.value), parseInt(month_selector.value)); } function create_page(year, month) { if (year < year_range['low'] || year > year_range['high']) return; var month_stuff = LunarCalendar.calendar(year, month, true); highlight_day = highlight_day > month_stuff['monthDays'] ? month_stuff['monthDays'] : highlight_day; var current_row = null; var current_cell = null; for (var row = 1; row < 7; row++) { if (calendar.rows.length === row) { current_row = calendar.insertRow(row); } else { current_row = calendar.rows[row]; } for (var column = 0; column < 7; column++) { if (current_row.cells.length === column) { current_cell = current_row.insertCell(column); current_cell.addEventListener('click', function() { highlight_day = parseInt(this.children[0].innerHTML); if (this.className === 'day_other_month') { return; } create_page(parseInt(year_selector.value), parseInt(month_selector.value)); }); } else { current_cell = current_row.cells[column]; } var index = (row - 1) * 7 + column; // [0, 7 * 6 - 1] /* * 注意判断顺序 * 1. 表格开头/结尾的非本月日期的单元格样式与其他单元格无关,需要最先判断 * 2. 其次是‘今天’的单元格样式 * 3. 再次是当前鼠标点击选中的单元格 * 4. 再次是属于周末的单元格 * 5. 最后是其他普通单元格 */ if (index < month_stuff['firstDay'] || index >= month_stuff['firstDay'] + month_stuff['monthDays']) { current_cell.className = 'day_other_month'; } else if (today.getDate() === month_stuff['monthData'][index]['day'] && today.getMonth() === month - 1 && today.getFullYear() === year) { current_cell.className = 'day_today'; } else if (index === highlight_day + month_stuff['firstDay'] - 1) { current_cell.className = 'day_highlight'; } else if (column === 0 || column === 6) { current_cell.className = 'day_weekend'; } else { current_cell.className = 'day_this_month'; } var lunar_day; if (month_stuff['monthData'][index]['lunarFestival']) { lunar_day = month_stuff['monthData'][index]['lunarFestival']; // } else if (month_stuff['monthData'][index]['solarFestival']) { // lunar_day = month_stuff['monthData'][index]['solarFestival']; } else { lunar_day = month_stuff['monthData'][index]['lunarDayName']; } var worktime = null; if (month_stuff['monthData'][index]['worktime'] === 2) { // worktime = document.createElement("SPAN"); worktime.className = 'worktime2'; // worktime.innerHTML = '休'; } else if (month_stuff['monthData'][index]['worktime'] === 1) { // worktime = document.createElement("SPAN"); worktime.className = 'worktime1'; // worktime.innerHTML = '班'; } else { } current_cell.innerHTML = '' + month_stuff['monthData'][index]['day'] + '' + '
' + '' + ''; if (worktime && current_cell.className !== 'day_other_month') { // current_cell.appendChild(worktime); } } } update_right_pane(year, month, highlight_day); month_stuff = null; } function new_month_selected() { if (this.parentNode.id === 'year_list') { year_selector.value = this.innerHTML; document.getElementById('year_div').className = 'hidden_div'; } else if (this.parentNode.id === 'month_list') { month_selector.value = this.innerHTML; document.getElementById('month_div').className = 'hidden_div'; } create_page(parseInt(year_selector.value), parseInt(month_selector.value)); } function popup_div(event) { var x = event.clientX - event.offsetX; var y = event.clientY - event.offsetY; var div; // TODO var width = 64; var height = 20; if (this.id === 'year_selector') { div = document.getElementById('year_div'); div_range.year.x_min = x; div_range.year.x_max = x + width; div_range.year.y_min = y; div_range.year.y_max = y + height; } else if (this.id === 'month_selector') { div = document.getElementById('month_div'); div_range.month.x_min = x; div_range.month.x_max = x + width; div_range.month.y_min = y; div_range.month.y_max = y + height; } /* else if (this.id === 'holiday_button') { div = document.getElementById('holiday_div'); div.style.width = '64px'; div.style.height = '100px'; div_range.holiday.x_min = x; div_range.holiday.x_max = x + width; div_range.holiday.y_min = y; div_range.holiday.y_max = y + height; }*/else { return; } if (div.className === 'hidden_div') { div.className = 'visible_div'; } else { div.className = 'hidden_div'; } div.style.left = x + 'px'; div.style.top = y + height + 'px'; } function update_right_pane(year, month, day) { var month_stuff = LunarCalendar.calendar(year, month, true); var general_datetime_list = document.getElementById('general_datetime_list'); var highlight_index = month_stuff['firstDay'] + day - 1; var lunar_month_name = month_stuff['monthData'][highlight_index]['lunarMonthName']; var lunar_day_name = month_stuff['monthData'][highlight_index]['lunarDayName']; var ganzhi_year = month_stuff['monthData'][highlight_index]['GanZhiYear']; var ganzhi_month = month_stuff['monthData'][highlight_index]['GanZhiMonth']; var ganzhi_day = month_stuff['monthData'][highlight_index]['GanZhiDay']; var zodiac = month_stuff['monthData'][highlight_index]['zodiac']; var weekday = weekdays[highlight_index % 7]; var month_str = month.toString(); if (month <= 9) { month_str = '0' + month; } var day_str = day.toString(); if (day <= 9) { day_str = '0' + day; } general_datetime_list.children[0].innerHTML = month_str + '-' + day_str + '-' + year + ' ' + weekday; general_datetime_list.children[1].innerHTML = day_str; // e.g. 06 general_datetime_list.children[2].innerHTML = ' '; general_datetime_list.children[3].innerHTML = ' '; general_datetime_list.children[4].innerHTML = ' '; //update_yiji_area(); month_stuff = null; } /* 节日查找从当月开始往后查找,包括公历节日、农历节日和农历节气,最多只查找到下一年 */ /*function go_to_holiday () { var year = today.getFullYear(); var month = today.getMonth() + 1; var day = 0; var month_stuff = LunarCalendar.calendar(year, month, false); var found = false; var target = this.innerHTML; do { for (var index = 0; index < month_stuff['monthDays']; index++) { if (target.indexOf(month_stuff['monthData'][index]['solarFestival']) >= 0 || target.indexOf(month_stuff['monthData'][index]['lunarFestival']) >= 0 || target.indexOf(month_stuff['monthData'][index]['term']) >= 0) { day = index + 1; found = true; break; } } if (found) { break; } if (month === 12) { year++; month = 1; } else { month++; } month_stuff = LunarCalendar.calendar(year, month, false); } while (year - today.getFullYear() <= 1); if (!found) { return; } year_selector.value = year; month_selector.value = month + 'Month'; highlight_day = day; create_page(year, month); month_stuff = null; }*/ ukui-panel-3.0.6.4/plugin-calendar/html/index.js0000644000175000017500000013737314204636772020063 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see 0) { scrollUp_count--; } else { scrollUp_count = 2; } } for(var index = 0; index <16; index++) { // li.children[0].children[index].innerHTML = '
'; //li.children[0].children[index].innerHTML = '
'+ list[index]+ '月'; li.children[0].children[index].innerHTML =''+ list[index]+ '月' + ''; // li.children[0].children[index].innerHTML = list[index]+ '月'; // document.getElementsByTagName('span').style="float:left;width:250px;background:#6C3;"; if(index >= bind_click_position) { if(scrollUp_count%3 ===2) { if(bind_click_count < 8) { li.children[0].children[index].style.color = "#FFFFFFFF"; li.children[0].children[index].addEventListener('click', new_month_selected); bind_click_count = bind_click_count + 1; } else { li.children[0].children[index].style.color = "#FFFFFF33"; li.children[0].children[index].addEventListener('click', new_month_selected_add); } continue; } if(bind_click_count < 12) // max bind _count of month click is no more than 12 { li.children[0].children[index].style.color = "#FFFFFFFF"; li.children[0].children[index].addEventListener('click', new_month_selected); bind_click_count = bind_click_count + 1; } else { li.children[0].children[index].style.color = "#FFFFFF33"; li.children[0].children[index].addEventListener('click', new_month_selected_add); } } else { li.children[0].children[index].style.color = "#FFFFFF33"; li.children[0].children[index].addEventListener('click', new_month_selected_minus); } } } function new_month_selected_add() { if (this.parentNode.className=== 'show_months') { var str = this.innerHTML.replace("",""); month_selector.value = str.replace("",""); document.getElementById('month_div').className = 'hidden_div'; calendar.style.display = ""; year = parseInt(year_selector.value); year++; year_selector.value = year + '年'; selected_date_div.innerHTML = year_selector.value + month_selector.value; create_page(parseInt(year_selector.value), parseInt(month_selector.value)); year--; } } function new_month_selected_minus() { if (this.parentNode.className=== 'show_months') { var str = this.innerHTML.replace("",""); month_selector.value = str.replace("",""); document.getElementById('month_div').className = 'hidden_div'; calendar.style.display = ""; year = parseInt(year_selector.value); year--; year_selector.value = year + '年'; selected_date_div.innerHTML = year_selector.value + month_selector.value; create_page(parseInt(year_selector.value), parseInt(month_selector.value)); year++; } } function update_year_month_ui() { var li = document.getElementById('year_div'); for (var index = 0; index < 16; index++) { // li.children[0].children[index].innerHTML = '
'; var curretYear = year + index; li.children[0].children[index].innerHTML= ''+curretYear+ '年' +'' ; //li.children[0].children[index].innerHTML= '
'+curretYear+ '年'; // if(index === 0) // { // li.children[0].children[index].style.backgroundColor = "#2b87a8"; // } li.children[0].children[index].addEventListener('click', new_month_selected); // new year implies new month // year_list.appendChild(li); // if (index === year) { // year_selector.value = index + '年'; // } } li = document.getElementById('month_div'); for (var index = 0; index < 16; index++) { li.children[0].children[index].removeEventListener('click', new_month_selected); li.children[0].children[index].style.color = "#FFFFFFFF"; if(index >=12) { var newIndex = index -12 + 1; li.children[0].children[index].style.color = "#FFFFFF33"; //li.children[0].children[index].innerHTML = '
' + new_index + '月'; li.children[0].children[index].innerHTML= ''+newIndex + '月' +'' ; //li.children[0].children[index].innerHTML = "1月"; } else { var newIndex = index + 1; //li.children[0].children[index].innerHTML ='
' + newIndex+ '月'; li.children[0].children[index].innerHTML =''+ newIndex+ '月' + '' ; } if(index < 12) { li.children[0].children[index].addEventListener('click', new_month_selected); } else { li.children[0].children[index].addEventListener('click', new_month_selected_add); } // month_list.appendChild(li); if (index === month + 1) { month_selector.value = index + '月'; } } } function updateUi() { year_selector.value = year + '年'; update_year_month_ui(); // var li = document.getElementById('year_div'); // for (var index = 0; index < 16; index++) { // li.children[0].children[index].innerHTML= year + index + '年'; // li.children[0].children[index].addEventListener('click', new_month_selected); // new year implies new month // // year_list.appendChild(li); // // if (index === year) { // // year_selector.value = index + '年'; // // } // } // li = document.getElementById('month_div'); // for (var index = 0; index < 16; index++) { // if(index >=12) // { // var new_index = index -12; // li.children[0].children[index].innerHTML = new_index +1+ '月'; // } // else // { // li.children[0].children[index].innerHTML = index +1+ '月'; // } // li.children[0].children[index].addEventListener('click', new_month_selected); // // month_list.appendChild(li); // if (index === month + 1) { // month_selector.value = index + '月'; // } // } } function scroll_div(event) { var e = event||window.event; if(e.wheelDelta > 0) { if(this.id === 'year_div') { year = year - 4; } else if(this.id === 'month_div') { scrollUp_count++; update_month_ui(0); return; } } else { if(this.id === 'year_div') { year = year + 4; } else if(this.id === 'month_div') { scrollDown_count++; update_month_ui(1); return; } } updateUi(); } function update_yiji_area_by_date(cur_year,cur_month) { "use strict"; var year = cur_year; var month = cur_month; var hl_table = document.getElementById('hl_table'); var current_row; var current_cell; if (year !== parseInt(hl_script.id, 10)) { load_hl_script(year); return; } if (typeof HuangLi['y' + year] === 'undefined') { for (var row = 0; row < 2; row++) { if (hl_table.rows.length === row) { current_row = hl_table.insertRow(row); } else { current_row = hl_table.rows[row]; } for (var column = 1; column < 5; column++) { if (current_row.cells.length === column) { current_cell = current_row.insertCell(column); } else { current_cell = current_row.cells[column]; } if (row === 1) { current_cell.innerHTML = '无数据'; } else { current_cell.innerHTML = ''; } } } } var day = highlight_day; var month_str = month.toString(); var day_str = day.toString(); if (month <= 9) { month_str = '0' + month; } if (day <= 9) { day_str = '0' + day; } var yi_str = HuangLi['y' + year]['d' + month_str + day_str]['y']; var ji_str = HuangLi['y' + year]['d' + month_str + day_str]['j']; var hl_yi_data = yi_str.split('.'); var hl_ji_data = ji_str.split('.'); for (var row = 0; row < 2; row++) { if (hl_table.rows.length === row) { current_row = hl_table.insertRow(row); } else { current_row = hl_table.rows[row]; } for (var column = 1; column < 5; column++) { if (current_row.cells.length === column) { current_cell = current_row.insertCell(column); } else { current_cell = current_row.cells[column]; } if(0 == row ) { if(hl_yi_data[column-1]) { current_cell.innerHTML = hl_yi_data[column-1]; } else { current_cell.innerHTML = ''; } } else { if(hl_ji_data[column-1]) { current_cell.innerHTML = hl_ji_data[column-1]; } else { current_cell.innerHTML =''; } } } } } function update_yiji_area() { "use strict"; var year = parseInt(year_selector.value, 10); var month = parseInt(month_selector.value, 10); var hl_table = document.getElementById('hl_table'); var current_row; var current_cell; if (year !== parseInt(hl_script.id, 10)) { load_hl_script(year); return; } if (typeof HuangLi['y' + year] === 'undefined') { for (var row = 0; row < 2; row++) { if (hl_table.rows.length === row) { current_row = hl_table.insertRow(row); } else { current_row = hl_table.rows[row]; } for (var column = 1; column < 5; column++) { if (current_row.cells.length === column) { current_cell = current_row.insertCell(column); } else { current_cell = current_row.cells[column]; } if (row === 1) { current_cell.innerHTML = '无数据'; } else { current_cell.innerHTML = ''; } } } } var day = highlight_day; var month_str = month.toString(); var day_str = day.toString(); if (month <= 9) { month_str = '0' + month; } if (day <= 9) { day_str = '0' + day; } var yi_str = HuangLi['y' + year]['d' + month_str + day_str]['y']; var ji_str = HuangLi['y' + year]['d' + month_str + day_str]['j']; var hl_yi_data = yi_str.split('.'); var hl_ji_data = ji_str.split('.'); for (var row = 0; row < 2; row++) { if (hl_table.rows.length === row) { current_row = hl_table.insertRow(row); } else { current_row = hl_table.rows[row]; } for (var column = 1; column < 5; column++) { if (current_row.cells.length === column) { current_cell = current_row.insertCell(column); } else { current_cell = current_row.cells[column]; } if(0 == row ) { if(hl_yi_data[column-1]) { current_cell.innerHTML = hl_yi_data[column-1]; } else { current_cell.innerHTML = ''; } } else { if(hl_ji_data[column-1]) { current_cell.innerHTML = hl_ji_data[column-1]; } else { current_cell.innerHTML =''; } } } } } function load_hl_script(year) { "use strict"; if (hl_script) { document.body.removeChild(hl_script); hl_script = null; } hl_script = document.createElement("SCRIPT"); hl_script.type = "text/javascript"; hl_script.src = "hl/hl" + year + '.js'; hl_script.id = year; hl_script.onload = function() { update_yiji_area(); }; document.body.appendChild(hl_script); } window.onload = function () { var checkbox = document.getElementById('advice_checkbox'); if (localStorage.getItem('hl_table') == "display"){ checkbox.setAttribute("checked", true); hl_table.setAttribute("style", "visibility:display"); //var zodiac_icon = document.getElementById('zodiac_icon'); //zodiac_icon.setAttribute("style", "display:none"); } checkbox.onclick = function(){ console.log("checkbox triggerd"); if(this.checked){ var hl_table = document.getElementById('hl_table'); hl_table.setAttribute("style", "visibility:display"); //var zodiac_icon = document.getElementById('zodiac_icon'); //zodiac_icon.setAttribute("style", "display:none"); localStorage.setItem('hl_table', "display"); } else{ var hl_table = document.getElementById('hl_table'); hl_table.setAttribute("style", "visibility:hidden"); // var zodiac_icon = document.getElementById('zodiac_icon'); // zodiac_icon.setAttribute("style", "display:block"); //zodiac_icon.setAttribute("style", "padding-top: 33px"); localStorage.setItem('hl_table', "hidden"); } } "use strict"; load_hl_script(today.getFullYear()); // var year_list = document.getElementById('year_list'); // var month_list = document.getElementById('month_list'); year = today.getFullYear(); month = today.getMonth(); var real_month = month + 1; //begin before modify year button selected_date_div = document.getElementById('selected_date_div'); year_selector = document.createElement('year_selector'); month_selector = document.createElement('month_selector'); year_selector.value = year + '年'; month_selector.value = real_month +'月'; selected_date_div.innerHTML = year_selector.value + month_selector.value; // year_selector = document.getElementById('year_selector'); // // year_selector.addEventListener('click', popup_div); // month_selector = document.getElementById('month_selector'); // month_selector.addEventListener('click', popup_div); //end // alert("begin"); year_button = document.getElementById('year_button'); year_button.addEventListener('click', popup_div); // alert("end"); month_button= document.getElementById('month_button'); month_button.addEventListener('click', popup_div); document.getElementById('year_div').addEventListener('mousewheel',scroll_div); document.getElementById('month_div').addEventListener('mousewheel',scroll_div); // year_button = document.getElementById('year_button'); // year_button.addEventListener('click', popup_div); // month_button = document.getElementById('month_button'); // month_button.addEventListener('click', popup_div); // document.addEventListener('mousewheel', function(event) // { // //alert("sroll??"); // }) document.addEventListener('click', function(event) { // var year_div = document.getElementById('year_div'); // var month_div = document.getElementById('month_div'); // var holiday_div = document.getElementById('holiday_div'); // var x = event.clientX; // var y = event.clientY; // if (year_div.className === 'visible_div') { // if (x > div_range.year.x_max || x < div_range.year.x_min || // y > div_range.year.y_max || y < div_range.year.y_min) { // year_div.className = 'hidden_div'; // } // } // if (month_div.className === 'visible_div') { // if (x > div_range.month.x_max || x < div_range.month.x_min || // y > div_range.month.y_max || y < div_range.month.y_min ) { // month_div.className = 'hidden_div'; // } // } // if (holiday_div.className === 'visible_div') { // if (x > div_range.holiday.x_max || x < div_range.holiday.x_min || // y > div_range.holiday.y_max || y < div_range.holiday.y_min ) { // holiday_div.className = 'hidden_div'; // } // } // var header_id=document.getElementById("header"); // var header_color=header_id.style.background; // var x=document.getElementsByClassName("day_highlight"); // if (header_color == "rgb(0, 0, 0)"){ // for (i = 0; i < x.length; i++) { // x[i].style.backgroundColor = "#2b87a8"; // } // var day_highlight_len=document.getElementsByClassName('day_highlight').length; // for (var i=0; i'; li.children[0].children[index].addEventListener('click', new_month_selected); // new year implies new month } } else if(this.id === 'go_next_month') { year = year + 16; year_selector.value = year + '年'; // selected_date_div.innerHTML = year_selector.value + month_selector.value; for (var index = 0; index < 16; index++) { // li.children[0].children[index].innerHTML = '
'; var currentYear = year + index; //li.children[0].children[index].innerHTML= '
'+ curretYear + '年'; li.children[0].children[index].innerHTML =''+ currentYear+ '年' + ''; li.children[0].children[index].addEventListener('click', new_month_selected); // new year implies new month } } return; } else if(document.getElementById('month_div').className ==='visible_div')//page the month ui { if(this.id === 'go_prev_month') { year --; year_selector.value = year + '年'; selected_date_div.innerHTML = year_selector.value + month_selector.value; } else if(this.id === 'go_next_month') { year++; year_selector.value = year + '年'; selected_date_div.innerHTML = year_selector.value + month_selector.value; } return; } // var year = parseInt(year_selector.value); // var month = parseInt(month_selector.value); var month_offset = (year - year_range['low']) * 12 + month - 1; // [0, n_months - 1] if (this.id === 'go_prev_year') { month_offset -= 12; } else if (this.id === 'go_next_year') { month_offset += 12; } else if (this.id === 'go_prev_month') { month_offset -= 1; } else if (this.id === 'go_next_month') { month_offset += 1; } else { return; } if (month_offset < 0 || month_offset > n_months - 1) { return; } year_selector.value = Math.floor(month_offset / 12) + year_range['low'] + '年'; month_selector.value = month_offset % 12 === 0 ? 1 +'月': month_offset % 12 + 1 + '月'; selected_date_div.innerHTML = year_selector.value + month_selector.value; NeedUpdateYijiArea = false; create_page(parseInt(year_selector.value), parseInt(month_selector.value)); NeedUpdateYijiArea = true; }); } var holidays = ['元旦节', '春节', '清明节', '劳动节', '端午节', '中秋节', '国庆节']; var holiday_list = document.getElementById('holiday_list'); for (var index = 0; index < holidays.length; index++) { var li = document.createElement('LI'); li.innerHTML = holidays[index]; li.addEventListener('click', go_to_holiday); holiday_list.appendChild(li); } //var holiday_button = document.getElementById('holiday_button'); //holiday_button.addEventListener('click', popup_div); var today_button = document.getElementById('today_button'); today_button.addEventListener('click', function() { year_selector.value = today.getFullYear() + '年'; month_selector.value = today.getMonth() + 1 + '月'; selected_date_div.innerHTML = year_selector.value + month_selector.value; highlight_day = today.getDate(); convertToNormal(); year = today.getFullYear(); month = today.getMonth(); if(PrevClick != null) { PrevClick.style.border = "none"; PrevClick = null; } create_page(today.getFullYear(), today.getMonth() + 1); update_year_month_ui(); var header_id=document.getElementById("header"); var header_color=header_id.style.background; var x=document.getElementsByClassName("day_today"); var i; if (header_color == "rgb(0, 0, 0)"){ for (i = 0; i < x.length; i++) { x[i].style.backgroundColor = "#3593b5"; } } else{ for (i = 0; i < x.length; i++) { x[i].style.backgroundColor = header_color; } } }); calendar = document.getElementById('calendar_table'); create_page(parseInt(year_selector.value), parseInt(month_selector.value)); } function create_page(year, month) { if (year < year_range['low'] || year > year_range['high']) return; var month_stuff = LunarCalendar.calendar(year, month, true,0); highlight_day = highlight_day > month_stuff['monthDays'] ? month_stuff['monthDays'] : highlight_day; var current_row = null; var current_cell = null; for (var row = 1; row < 7; row++) { if (calendar.rows.length === row) { current_row = calendar.insertRow(row); } else { current_row = calendar.rows[row]; } for (var column = 0; column < 7; column++) { if (current_row.cells.length === column) { current_cell = current_row.insertCell(column); current_cell.addEventListener('click', function() { // if(this.children[0].innerHTML === "") // { // highlight_day = parseInt(this.children[1].innerHTML); // } // else // { highlight_day = parseInt(this.children[0].innerHTML); // } //highlight_day = parseInt(this.children[0].innerText); var cur_month = parseInt(month_selector.value); var cur_year = parseInt(year_selector.value); if(PrevClick != null) { PrevClick.style.border = "none"; } this.style.border = "1px solid #7eb4ea"; PrevClick = this; if (this.className === 'day_other_month' && highlight_day > 20) { // var cur_month = parseInt(month_selector.value); // var cur_year = parseInt(year_selector.value); if(1 == cur_month) { cur_month = 12; cur_year = cur_year - 1; } else { cur_month = cur_month - 1; } // create_page(cur_year, cur_month); update_right_pane(cur_year, cur_month, highlight_day); update_yiji_area_by_date(cur_year,cur_month); } else if(this.className === 'day_other_month' && highlight_day < 15) { // var cur_month = parseInt(month_selector.value); // var cur_year = parseInt(year_selector.value); if(12 == cur_month) { cur_month = 1; cur_year = cur_year + 1; } else { cur_month = cur_month + 1; } // create_page(cur_year, cur_month); update_right_pane(cur_year, cur_month, highlight_day); update_yiji_area_by_date(cur_year,cur_month); } else { create_page(parseInt(year_selector.value), parseInt(month_selector.value)); } // create_page(cur_year, cur_month); }); } else { current_cell = current_row.cells[column]; } // var header_id=document.getElementById("header"); // var header_color=header_id.style.background; // if (header_color == "rgb(0, 0, 0)"){ // var x=document.getElementsByClassName("day_highlight"); // for (i = 0; i < x.length; i++) { // x[i].style.backgroundColor = "#151a1e"; // } // } // else{ // var x=document.getElementsByClassName("day_highlight"); // for (i = 0; i < x.length; i++) { // x[i].style.backgroundColor = "#ffffff"; // } // } // if((year == today.getFullYear()) && (month == today.getMonth())) // { // var x=document.getElementsByClassName("day_today"); // for (i = 0; i < x.length; i++) { // // x[i].style.backgroundColor = "#3593b5"; // x[i].style.backgroundColor = "#3d6be5"; // } // } // x=document.getElementsByClassName("day_today"); // for (i = 0; i < x.length; i++) { // // x[i].style.backgroundColor = "#3593b5"; // x[i].style.backgroundColor = "#3d6be5"; // } var index = (row - 1) * 7 + column; // [0, 7 * 6 - 1] /* * 注意判断顺序 * 1. 表格开头/结尾的非本月日期的单元格样式与其他单元格无关,需要最先判断 * 2. 其次是‘今天’的单元格样式 * 3. 再次是当前鼠标点击选中的单元格 * 4. 再次是属于周末的单元格 * 5. 最后是其他普通单元格 */ if (index < month_stuff['firstDay'] || index >= month_stuff['firstDay'] + month_stuff['monthDays']) { current_cell.className = 'day_other_month'; } else if (today.getDate() === month_stuff['monthData'][index]['day'] && today.getMonth() === month - 1 && today.getFullYear() === year) { current_cell.className = 'day_today'; } else if (index === highlight_day + month_stuff['firstDay'] - 1) { current_cell.className = 'day_highlight'; } else if (column === 0 || column === 6) { current_cell.className = 'day_weekend'; } else { current_cell.className = 'day_this_month'; } var lunar_day; if ((month_stuff['monthData'][index]['lunarFestival'])&&(month_stuff['monthData'][index]['solarFestival'])){ lunar_day = month_stuff['monthData'][index]['solarFestival']; }else if (month_stuff['monthData'][index]['solarFestival']) { lunar_day = month_stuff['monthData'][index]['solarFestival']; }else if(month_stuff['monthData'][index]['lunarFestival']){ lunar_day = month_stuff['monthData'][index]['lunarFestival']; }else if(month_stuff['monthData'][index]['term']){ lunar_day = month_stuff['monthData'][index]['term']; }else { lunar_day = month_stuff['monthData'][index]['lunarDayName']; } // if (month_stuff['monthData'][index]['lunarFestival']) // { // lunar_day = month_stuff['monthData'][index]['lunarFestival']; // // } else if (month_stuff['monthData'][index]['solarFestival']) { // // lunar_day = month_stuff['monthData'][index]['solarFestival']; // } else { // lunar_day = month_stuff['monthData'][index]['lunarDayName']; // } var worktime = null; if (month_stuff['monthData'][index]['worktime'] === 2) { worktime = document.createElement("SPAN"); worktime.className = 'worktime2'; worktime.innerHTML = '休'; } else if (month_stuff['monthData'][index]['worktime'] === 1) { worktime = document.createElement("SPAN"); worktime.className = 'worktime1'; worktime.innerHTML = '班'; } else { } current_cell.innerHTML = '' + month_stuff['monthData'][index]['day'] + '' + '
' + '' + lunar_day + ''; // if (worktime && current_cell.className !== 'day_other_month') { // current_cell.appendChild(worktime); // } if (worktime) { current_cell.appendChild(worktime); } // if (month_stuff['monthData'][index]['worktime'] === 2) { // worktime = document.createElement("SPAN"); // worktime.className = 'worktime2'; // worktime.innerHTML = ' '; // } else if (month_stuff['monthData'][index]['worktime'] === 1) { // worktime = document.createElement("SPAN"); // worktime.className = 'worktime1'; // worktime.innerHTML = ' '; // } else { // } // if (worktime && current_cell.className !== 'day_other_month') { // current_cell.innerHTML = worktime.innerHTML+ // ' ' + // month_stuff['monthData'][index]['day'] + // '' + // '
' + // '' + // lunar_day + // ''; // } // else // { // current_cell.innerHTML = '' + // month_stuff['monthData'][index]['day'] + // '' + // '
' + // '' + // lunar_day + // ''; // } } } update_right_pane(year, month, highlight_day); month_stuff = null; if (header_color == "rgb(0, 0, 0)"){ var day_this_month_len=document.getElementsByClassName('day_this_month').length; for (var i=0; i",""); year_selector.value = str.replace("",""); document.getElementById('year_div').className = 'hidden_div'; calendar.style.display = ""; } else if (this.parentNode.className=== 'show_months') { var str = this.innerHTML.replace("",""); month_selector.value = str.replace("",""); document.getElementById('month_div').className = 'hidden_div'; calendar.style.display = ""; } selected_date_div.innerHTML = year_selector.value + month_selector.value; create_page(parseInt(year_selector.value), parseInt(month_selector.value)); } function popup_div(event) { var x = event.clientX - event.offsetX; var y = event.clientY - event.offsetY; var div; // TODO var width = 64; var height = 20; if (this.id === 'year_button') { div = document.getElementById('year_div'); div_range.year.x_min = x; div_range.year.x_max = x + width; div_range.year.y_min = y; div_range.year.y_max = y + height; if (div.className === 'hidden_div') { div.className = 'visible_div'; document.getElementById('month_div').className = 'hidden_div'; calendar.style.display = "none"; year = parseInt(year_selector.value); var li = document.getElementById('year_div'); year_selector.value = year + '年'; // selected_date_div.innerHTML = year_selector.value + month_selector.value; for (var index = 0; index < 16; index++) { // li.children[0].children[index].innerHTML = '
'; var currentYear = year + index; //li.children[0].children[index].innerHTML= '
' + curretYear + '年'; li.children[0].children[index].innerHTML =''+ currentYear+ '年' + ''; li.children[0].children[index].addEventListener('click', new_month_selected); // new year implies new month } } else { div.className = 'hidden_div'; calendar.style.display = ""; } } else if (this.id === 'month_button') { div = document.getElementById('month_div'); div_range.month.x_min = x; div_range.month.x_max = x + width; div_range.month.y_min = y; div_range.month.y_max = y + height; if (div.className === 'hidden_div') { div.className = 'visible_div'; document.getElementById('year_div').className = 'hidden_div'; calendar.style.display = "none"; } else { div.className = 'hidden_div'; calendar.style.display = ""; } } else { return; } // if (div.className === 'hidden_div') { // div.className = 'visible_div'; // calendar.style.display = "none"; // } else { // div.className = 'hidden_div'; // calendar.style.display = ""; // } div.style.left = x + 'px'; div.style.top = y + height + 'px'; update_year_month_ui(); //updateUi(); } function update_right_pane(year, month, day) { var month_stuff = LunarCalendar.calendar(year, month, true, 0); var general_datetime_list = document.getElementById('general_datetime_list'); var datetime_container = document.getElementById('datetime_container'); var highlight_index = month_stuff['firstDay'] + day - 1; var lunar_month_name = month_stuff['monthData'][highlight_index]['lunarMonthName']; var lunar_day_name = month_stuff['monthData'][highlight_index]['lunarDayName']; var ganzhi_year = month_stuff['monthData'][highlight_index]['GanZhiYear']; var ganzhi_month = month_stuff['monthData'][highlight_index]['GanZhiMonth']; var ganzhi_day = month_stuff['monthData'][highlight_index]['GanZhiDay']; var zodiac = month_stuff['monthData'][highlight_index]['zodiac']; var weekday = weekdays[highlight_index % 7]; var month_str = month.toString(); if (month <= 9) { month_str = '0' + month; } var day_str = day.toString(); if (day <= 9) { day_str = '0' + day; } if(NeedChangeCurrentTime) { datetime_container.children[1].innerHTML = year + '-' + month_str + '-' + day_str + ' 星期' + weekday + ' '+lunar_month_name + lunar_day_name; NeedChangeCurrentTime = 0; } /* general_datetime_list.children[0].innerHTML = year + '-' + month_str + '-' + day_str + ' 星期' + weekday; general_datetime_list.children[1].innerHTML = day_str; // e.g. 06 general_datetime_list.children[2].innerHTML = lunar_month_name + lunar_day_name;*/ //general_datetime_list.children[0].innerHTML = ganzhi_year + '年' + '【' + zodiac + '年' + '】' + ganzhi_month + '月 ' + ganzhi_day + '日'; // general_datetime_list.children[1].innerHTML = ganzhi_month + '月 ' + ganzhi_day + '日'; updateTime(); if(NeedUpdateYijiArea) { general_datetime_list.children[0].innerHTML = lunar_month_name + lunar_day_name +'    '+ ganzhi_year + '年' + '【' + zodiac + '年' + '】' + ganzhi_month + '月 ' + ganzhi_day + '日'; update_yiji_area(); } NeedUpdateYijiArea = true; month_stuff = null; } /* 节日查找从当月开始往后查找,包括公历节日、农历节日和农历节气,最多只查找到下一年 */ function go_to_holiday () { var year = today.getFullYear(); var month = today.getMonth() + 1; var day = 0; var month_stuff = LunarCalendar.calendar(year, month, false, 0); var found = false; var target = this.innerHTML; do { for (var index = 0; index < month_stuff['monthDays']; index++) { if (target.indexOf(month_stuff['monthData'][index]['solarFestival']) >= 0 || target.indexOf(month_stuff['monthData'][index]['lunarFestival']) >= 0 || target.indexOf(month_stuff['monthData'][index]['term']) >= 0) { day = index + 1; found = true; break; } } if (found) { break; } if (month === 12) { year++; month = 1; } else { month++; } month_stuff = LunarCalendar.calendar(year, month, false, 0); } while (year - today.getFullYear() <= 1); if (!found) { return; } year_selector.value = year + '年'; month_selector.value = month + '月'; highlight_day = day; create_page(year, month); month_stuff = null; } ukui-panel-3.0.6.4/plugin-calendar/html/ukui-solar-en.html0000644000175000017500000001001114204636772021752 0ustar fengfeng

12:42:53

2020-01-01

2020.3
Sun Mon Tue Wed Thur Fri Sat
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
ukui-panel-3.0.6.4/plugin-calendar/html/hl/0000755000175000017500000000000014204636776017007 5ustar fengfengukui-panel-3.0.6.4/plugin-calendar/html/hl/hl2022.js0000644000175000017500000006716614204636772020272 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see 0) { scrollUp_count--; } else { scrollUp_count = 2; } } for(var index = 0; index <16; index++) { // li.children[0].children[index].innerHTML = '
'; //li.children[0].children[index].innerHTML = '
'+ list[index]+ '月'; li.children[0].children[index].innerHTML =''+ list[index]+ '月' + ''; // li.children[0].children[index].innerHTML = list[index]+ '月'; // document.getElementsByTagName('span').style="float:left;width:250px;background:#6C3;"; if(index >= bind_click_position) { if(scrollUp_count%3 ===2) { if(bind_click_count < 8) { li.children[0].children[index].style.color = "#FFFFFFFF"; li.children[0].children[index].addEventListener('click', new_month_selected); bind_click_count = bind_click_count + 1; } else { li.children[0].children[index].style.color = "#FFFFFF33"; li.children[0].children[index].addEventListener('click', new_month_selected_add); } continue; } if(bind_click_count < 12) // max bind _count of month click is no more than 12 { li.children[0].children[index].style.color = "#FFFFFFFF"; li.children[0].children[index].addEventListener('click', new_month_selected); bind_click_count = bind_click_count + 1; } else { li.children[0].children[index].style.color = "#FFFFFF33"; li.children[0].children[index].addEventListener('click', new_month_selected_add); } } else { li.children[0].children[index].style.color = "#FFFFFF33"; li.children[0].children[index].addEventListener('click', new_month_selected_minus); } } } function new_month_selected_add() { if (this.parentNode.className=== 'show_months') { var str = this.innerHTML.replace("",""); month_selector.value = str.replace("",""); document.getElementById('month_div').className = 'hidden_div'; calendar.style.display = ""; year = parseInt(year_selector.value); year++; year_selector.value = year + '年'; selected_date_div.innerHTML = year_selector.value + month_selector.value; create_page(parseInt(year_selector.value), parseInt(month_selector.value)); year--; } } function new_month_selected_minus() { if (this.parentNode.className=== 'show_months') { var str = this.innerHTML.replace("",""); month_selector.value = str.replace("",""); document.getElementById('month_div').className = 'hidden_div'; calendar.style.display = ""; year = parseInt(year_selector.value); year--; year_selector.value = year + '年'; selected_date_div.innerHTML = year_selector.value + month_selector.value; create_page(parseInt(year_selector.value), parseInt(month_selector.value)); year++; } } function update_year_month_ui() { var li = document.getElementById('year_div'); for (var index = 0; index < 16; index++) { // li.children[0].children[index].innerHTML = '
'; var curretYear = year + index; li.children[0].children[index].innerHTML= ''+curretYear+ '年' +'' ; //li.children[0].children[index].innerHTML= '
'+curretYear+ '年'; // if(index === 0) // { // li.children[0].children[index].style.backgroundColor = "#2b87a8"; // } li.children[0].children[index].addEventListener('click', new_month_selected); // new year implies new month // year_list.appendChild(li); // if (index === year) { // year_selector.value = index + '年'; // } } li = document.getElementById('month_div'); for (var index = 0; index < 16; index++) { li.children[0].children[index].removeEventListener('click', new_month_selected); li.children[0].children[index].style.color = "#FFFFFFFF"; if(index >=12) { var newIndex = index -12 + 1; li.children[0].children[index].style.color = "#FFFFFF33"; //li.children[0].children[index].innerHTML = '
' + new_index + '月'; li.children[0].children[index].innerHTML= ''+newIndex + '月' +'' ; //li.children[0].children[index].innerHTML = "1月"; } else { var newIndex = index + 1; //li.children[0].children[index].innerHTML ='
' + newIndex+ '月'; li.children[0].children[index].innerHTML =''+ newIndex+ '月' + '' ; } if(index < 12) { li.children[0].children[index].addEventListener('click', new_month_selected); } else { li.children[0].children[index].addEventListener('click', new_month_selected_add); } // month_list.appendChild(li); if (index === month + 1) { month_selector.value = index + '月'; } } } function updateUi() { year_selector.value = year + '年'; update_year_month_ui(); // var li = document.getElementById('year_div'); // for (var index = 0; index < 16; index++) { // li.children[0].children[index].innerHTML= year + index + '年'; // li.children[0].children[index].addEventListener('click', new_month_selected); // new year implies new month // // year_list.appendChild(li); // // if (index === year) { // // year_selector.value = index + '年'; // // } // } // li = document.getElementById('month_div'); // for (var index = 0; index < 16; index++) { // if(index >=12) // { // var new_index = index -12; // li.children[0].children[index].innerHTML = new_index +1+ '月'; // } // else // { // li.children[0].children[index].innerHTML = index +1+ '月'; // } // li.children[0].children[index].addEventListener('click', new_month_selected); // // month_list.appendChild(li); // if (index === month + 1) { // month_selector.value = index + '月'; // } // } } function scroll_div(event) { var e = event||window.event; if(e.wheelDelta > 0) { if(this.id === 'year_div') { year = year - 4; } else if(this.id === 'month_div') { scrollUp_count++; update_month_ui(0); return; } } else { if(this.id === 'year_div') { year = year + 4; } else if(this.id === 'month_div') { scrollDown_count++; update_month_ui(1); return; } } updateUi(); } function update_yiji_area() { "use strict"; var year = parseInt(year_selector.value, 10); var month = parseInt(month_selector.value, 10); var hl_table = document.getElementById('hl_table'); var current_row; var current_cell; if (year !== parseInt(hl_script.id, 10)) { load_hl_script(year); return; } if (typeof HuangLi['y' + year] === 'undefined') { for (var row = 0; row < 2; row++) { if (hl_table.rows.length === row) { current_row = hl_table.insertRow(row); } else { current_row = hl_table.rows[row]; } for (var column = 1; column < 5; column++) { if (current_row.cells.length === column) { current_cell = current_row.insertCell(column); } else { current_cell = current_row.cells[column]; } if (row === 1) { current_cell.innerHTML = '无数据'; } else { current_cell.innerHTML = ''; } } } } var day = highlight_day; var month_str = month.toString(); var day_str = day.toString(); if (month <= 9) { month_str = '0' + month; } if (day <= 9) { day_str = '0' + day; } var yi_str = HuangLi['y' + year]['d' + month_str + day_str]['y']; var ji_str = HuangLi['y' + year]['d' + month_str + day_str]['j']; var hl_yi_data = yi_str.split('.'); var hl_ji_data = ji_str.split('.'); for (var row = 0; row < 2; row++) { if (hl_table.rows.length === row) { current_row = hl_table.insertRow(row); } else { current_row = hl_table.rows[row]; } for (var column = 1; column < 5; column++) { if (current_row.cells.length === column) { current_cell = current_row.insertCell(column); } else { current_cell = current_row.cells[column]; } if(0 == row ) { if(hl_yi_data[column-1]) { current_cell.innerHTML = hl_yi_data[column-1]; } else { current_cell.innerHTML = ''; } } else { if(hl_ji_data[column-1]) { current_cell.innerHTML = hl_ji_data[column-1]; } else { current_cell.innerHTML =''; } } } } } function load_hl_script(year) { "use strict"; if (hl_script) { document.body.removeChild(hl_script); hl_script = null; } hl_script = document.createElement("SCRIPT"); hl_script.type = "text/javascript"; hl_script.src = "hl/hl" + year + '.js'; hl_script.id = year; hl_script.onload = function() { update_yiji_area(); }; document.body.appendChild(hl_script); } window.onload = function () { "use strict"; load_hl_script(today.getFullYear()); // var year_list = document.getElementById('year_list'); // var month_list = document.getElementById('month_list'); year = today.getFullYear(); month = today.getMonth(); var real_month = month + 1; selected_date_div = document.getElementById('selected_date_div'); year_selector = document.createElement('year_selector'); month_selector = document.createElement('month_selector'); year_selector.value = year + '年'; month_selector.value = real_month +'月'; selected_date_div.innerHTML = year_selector.value + month_selector.value; // year_selector = document.getElementById('year_selector'); // // year_selector.addEventListener('click', popup_div); // month_selector = document.getElementById('month_selector'); // month_selector.addEventListener('click', popup_div); //end // alert("begin"); year_button = document.getElementById('year_button'); year_button.addEventListener('click', popup_div); // alert("end"); month_button= document.getElementById('month_button'); month_button.addEventListener('click', popup_div); document.getElementById('year_div').addEventListener('mousewheel',scroll_div); document.getElementById('month_div').addEventListener('mousewheel',scroll_div); document.addEventListener('click', function(event) { }); updateUi(); var goto_arrows = document.getElementsByTagName('input'); var n_months = (year_range['high'] - year_range['low'] + 1) * 12; for (var index = 0; index < goto_arrows.length; index++) { goto_arrows[index].addEventListener('click', function() { var year = parseInt(year_selector.value); var month = parseInt(month_selector.value); if(PrevClick != null) { PrevClick.style.border = "none"; PrevClick = null; } //page the year ui if(document.getElementById('year_div').className ==='visible_div') { var li = document.getElementById('year_div'); if(this.id === 'go_prev_month') { year = year -16; year_selector.value = year + '年'; // selected_date_div.innerHTML = year_selector.value + month_selector.value; for (var index = 0; index < 16; index++) { // li.children[0].children[index].innerHTML = '
'; var currentYear = year + index; //li.children[0].children[index].innerHTML= '
' + curretYear + '年'; li.children[0].children[index].innerHTML =''+ currentYear+ '年' + ''; li.children[0].children[index].addEventListener('click', new_month_selected); // new year implies new month } } else if(this.id === 'go_next_month') { year = year + 16; year_selector.value = year + '年'; // selected_date_div.innerHTML = year_selector.value + month_selector.value; for (var index = 0; index < 16; index++) { // li.children[0].children[index].innerHTML = '
'; var currentYear = year + index; //li.children[0].children[index].innerHTML= '
'+ curretYear + '年'; li.children[0].children[index].innerHTML =''+ currentYear+ '年' + ''; li.children[0].children[index].addEventListener('click', new_month_selected); // new year implies new month } } return; } else if(document.getElementById('month_div').className ==='visible_div')//page the month ui { if(this.id === 'go_prev_month') { year --; year_selector.value = year + '年'; selected_date_div.innerHTML = year_selector.value + month_selector.value; } else if(this.id === 'go_next_month') { year++; year_selector.value = year + '年'; selected_date_div.innerHTML = year_selector.value + month_selector.value; } return; } // var year = parseInt(year_selector.value); // var month = parseInt(month_selector.value); var month_offset = (year - year_range['low']) * 12 + month - 1; // [0, n_months - 1] if (this.id === 'go_prev_year') { month_offset -= 12; } else if (this.id === 'go_next_year') { month_offset += 12; } else if (this.id === 'go_prev_month') { month_offset -= 1; } else if (this.id === 'go_next_month') { month_offset += 1; } else { return; } if (month_offset < 0 || month_offset > n_months - 1) { return; } year_selector.value = Math.floor(month_offset / 12) + year_range['low'] + '年'; month_selector.value = month_offset % 12 === 0 ? 1 +'月': month_offset % 12 + 1 + '月'; selected_date_div.innerHTML = year_selector.value + month_selector.value; create_page(parseInt(year_selector.value), parseInt(month_selector.value)); }); } var holidays = ['元旦节', '春节', '清明节', '劳动节', '端午节', '中秋节', '国庆节']; var holiday_list = document.getElementById('holiday_list'); for (var index = 0; index < holidays.length; index++) { var li = document.createElement('LI'); li.innerHTML = holidays[index]; li.addEventListener('click', go_to_holiday); holiday_list.appendChild(li); } //var holiday_button = document.getElementById('holiday_button'); //holiday_button.addEventListener('click', popup_div); var today_button = document.getElementById('today_button'); today_button.addEventListener('click', function() { year_selector.value = today.getFullYear() + '年'; month_selector.value = today.getMonth() + 1 + '月'; selected_date_div.innerHTML = year_selector.value + month_selector.value; highlight_day = today.getDate(); convertToNormal(); year = today.getFullYear(); month = today.getMonth(); if(PrevClick != null) { PrevClick.style.border = "none"; PrevClick = null; } create_page(today.getFullYear(), today.getMonth() + 1); update_year_month_ui(); var header_id=document.getElementById("header"); var header_color=header_id.style.background; var x=document.getElementsByClassName("day_today"); var i; if (header_color == "rgb(0, 0, 0)"){ for (i = 0; i < x.length; i++) { x[i].style.backgroundColor = "#3593b5"; } } else{ for (i = 0; i < x.length; i++) { x[i].style.backgroundColor = header_color; } } }); calendar = document.getElementById('calendar_table'); create_page(parseInt(year_selector.value), parseInt(month_selector.value)); } function create_page(year, month) { if (year < year_range['low'] || year > year_range['high']) return; var month_stuff = LunarCalendar.calendar(year, month, true,1); highlight_day = highlight_day > month_stuff['monthDays'] ? month_stuff['monthDays'] : highlight_day; var current_row = null; var current_cell = null; for (var row = 1; row < 7; row++) { if (calendar.rows.length === row) { current_row = calendar.insertRow(row); } else { current_row = calendar.rows[row]; } for (var column = 0; column < 7; column++) { if (current_row.cells.length === column) { current_cell = current_row.insertCell(column); current_cell.addEventListener('click', function() { highlight_day = parseInt(this.children[0].innerHTML); if(PrevClick != null) { PrevClick.style.border = "none"; } this.style.border = "1px solid #7eb4ea"; PrevClick = this; if (this.className === 'day_other_month') { return; } create_page(parseInt(year_selector.value), parseInt(month_selector.value)); }); } else { current_cell = current_row.cells[column]; } var index = (row - 1) * 7 + column; // [0, 7 * 6 - 1] /* * 注意判断顺序 * 1. 表格开头/结尾的非本月日期的单元格样式与其他单元格无关,需要最先判断 * 2. 其次是‘今天’的单元格样式 * 3. 再次是当前鼠标点击选中的单元格 * 4. 再次是属于周末的单元格 * 5. 最后是其他普通单元格 */ if ((index < (month_stuff['firstDay'] -1) && month_stuff['firstDay'] != 0)//每周从周一开始,当月第一天不是星期天,上个月的日期 ||(index < 6 && month_stuff['firstDay'] === 0)//第一天是星期天 || (month_stuff['firstDay']===0 && index >= (month_stuff['monthDays'] + 6))//第一天是星期天下月的日期 ||( month_stuff['firstDay'] != 0 && index >= month_stuff['firstDay'] + month_stuff['monthDays']-1)) //第一天不是星期天下月日期 { current_cell.className = 'day_other_month'; } else if (today.getDate() === month_stuff['monthData'][index]['day'] && today.getMonth() === month - 1 && today.getFullYear() === year) { current_cell.className = 'day_today'; } else if (index === highlight_day + month_stuff['firstDay'] - 1) { current_cell.className = 'day_highlight'; } else if (column === 0 || column === 6) { current_cell.className = 'day_weekend'; } else { current_cell.className = 'day_this_month'; } var lunar_day; if (month_stuff['monthData'][index]['lunarFestival']) { lunar_day = month_stuff['monthData'][index]['lunarFestival']; // } else if (month_stuff['monthData'][index]['solarFestival']) { // lunar_day = month_stuff['monthData'][index]['solarFestival']; } else { lunar_day = month_stuff['monthData'][index]['lunarDayName']; } var worktime = null; if (month_stuff['monthData'][index]['worktime'] === 2) { worktime = document.createElement("SPAN"); worktime.className = 'worktime2'; worktime.innerHTML = '休'; } else if (month_stuff['monthData'][index]['worktime'] === 1) { worktime = document.createElement("SPAN"); worktime.className = 'worktime1'; worktime.innerHTML = '班'; } else { } current_cell.innerHTML = '' + month_stuff['monthData'][index]['day'] + '' // if (worktime && current_cell.className !== 'day_other_month') { // current_cell.appendChild(worktime); // } if (worktime) { current_cell.appendChild(worktime); } // if (month_stuff['monthData'][index]['worktime'] === 2) { // worktime = document.createElement("SPAN"); // worktime.className = 'worktime2'; // worktime.innerHTML = ' '; // } else if (month_stuff['monthData'][index]['worktime'] === 1) { // worktime = document.createElement("SPAN"); // worktime.className = 'worktime1'; // worktime.innerHTML = ' '; // } else { // } // if (worktime && current_cell.className !== 'day_other_month') { // current_cell.innerHTML = worktime.innerHTML+ // ' ' + // month_stuff['monthData'][index]['day'] + // '' + // '
' + // '' + // lunar_day + // ''; // } // else // { // current_cell.innerHTML = '' + // month_stuff['monthData'][index]['day'] + // '' + // '
' + // '' + // lunar_day + // ''; // } } } update_right_pane(year, month, highlight_day); month_stuff = null; if (header_color == "rgb(0, 0, 0)"){ var day_this_month_len=document.getElementsByClassName('day_this_month').length; for (var i=0; i",""); year_selector.value = str.replace("",""); document.getElementById('year_div').className = 'hidden_div'; calendar.style.display = ""; } else if (this.parentNode.className=== 'show_months') { var str = this.innerHTML.replace("",""); month_selector.value = str.replace("",""); document.getElementById('month_div').className = 'hidden_div'; calendar.style.display = ""; } selected_date_div.innerHTML = year_selector.value + month_selector.value; create_page(parseInt(year_selector.value), parseInt(month_selector.value)); } function popup_div(event) { var x = event.clientX - event.offsetX; var y = event.clientY - event.offsetY; var div; // TODO var width = 64; var height = 20; if (this.id === 'year_button') { div = document.getElementById('year_div'); div_range.year.x_min = x; div_range.year.x_max = x + width; div_range.year.y_min = y; div_range.year.y_max = y + height; if (div.className === 'hidden_div') { div.className = 'visible_div'; document.getElementById('month_div').className = 'hidden_div'; calendar.style.display = "none"; year = parseInt(year_selector.value); var li = document.getElementById('year_div'); year_selector.value = year + '年'; // selected_date_div.innerHTML = year_selector.value + month_selector.value; for (var index = 0; index < 16; index++) { // li.children[0].children[index].innerHTML = '
'; var currentYear = year + index; //li.children[0].children[index].innerHTML= '
' + curretYear + '年'; li.children[0].children[index].innerHTML =''+ currentYear+ '年' + ''; li.children[0].children[index].addEventListener('click', new_month_selected); // new year implies new month } } else { div.className = 'hidden_div'; calendar.style.display = ""; } } else if (this.id === 'month_button') { div = document.getElementById('month_div'); div_range.month.x_min = x; div_range.month.x_max = x + width; div_range.month.y_min = y; div_range.month.y_max = y + height; if (div.className === 'hidden_div') { div.className = 'visible_div'; document.getElementById('year_div').className = 'hidden_div'; calendar.style.display = "none"; } else { div.className = 'hidden_div'; calendar.style.display = ""; } } else { return; } // if (div.className === 'hidden_div') { // div.className = 'visible_div'; // calendar.style.display = "none"; // } else { // div.className = 'hidden_div'; // calendar.style.display = ""; // } div.style.left = x + 'px'; div.style.top = y + height + 'px'; update_year_month_ui(); //updateUi(); } function update_right_pane(year, month, day) { var month_stuff = LunarCalendar.calendar(year, month, true, 1); var general_datetime_list = document.getElementById('general_datetime_list'); var datetime_container = document.getElementById('datetime_container'); var highlight_index = month_stuff['firstDay'] + day - 1; var lunar_month_name = month_stuff['monthData'][highlight_index]['lunarMonthName']; var lunar_day_name = month_stuff['monthData'][highlight_index]['lunarDayName']; var ganzhi_year = month_stuff['monthData'][highlight_index]['GanZhiYear']; var ganzhi_month = month_stuff['monthData'][highlight_index]['GanZhiMonth']; var ganzhi_day = month_stuff['monthData'][highlight_index]['GanZhiDay']; var zodiac = month_stuff['monthData'][highlight_index]['zodiac']; var weekday = weekdays[highlight_index % 7]; var month_str = month.toString(); if (month <= 9) { month_str = '0' + month; } var day_str = day.toString(); if (day <= 9) { day_str = '0' + day; } if(NeedChangeCurrentTime) { datetime_container.children[1].innerHTML = year + '-' + month_str + '-' + day_str + ' 星期' + weekday /* + ' '+lunar_month_name + lunar_day_name*/; NeedChangeCurrentTime = 0; } /* general_datetime_list.children[0].innerHTML = year + '-' + month_str + '-' + day_str + ' 星期' + weekday; general_datetime_list.children[1].innerHTML = day_str; // e.g. 06 general_datetime_list.children[2].innerHTML = lunar_month_name + lunar_day_name;*/ //general_datetime_list.children[0].innerHTML = ganzhi_year + '年' + '【' + zodiac + '年' + '】' + ganzhi_month + '月 ' + ganzhi_day + '日'; // general_datetime_list.children[1].innerHTML = ganzhi_month + '月 ' + ganzhi_day + '日'; updateTime(); update_yiji_area(); month_stuff = null; } /* 节日查找从当月开始往后查找,包括公历节日、农历节日和农历节气,最多只查找到下一年 */ function go_to_holiday () { var year = today.getFullYear(); var month = today.getMonth() + 1; var day = 0; var month_stuff = LunarCalendar.calendar(year, month, false, 1); var found = false; var target = this.innerHTML; do { for (var index = 0; index < month_stuff['monthDays']; index++) { if (target.indexOf(month_stuff['monthData'][index]['solarFestival']) >= 0 || target.indexOf(month_stuff['monthData'][index]['lunarFestival']) >= 0 || target.indexOf(month_stuff['monthData'][index]['term']) >= 0) { day = index + 1; found = true; break; } } if (found) { break; } if (month === 12) { year++; month = 1; } else { month++; } month_stuff = LunarCalendar.calendar(year, month, false, 1); } while (year - today.getFullYear() <= 1); if (!found) { return; } year_selector.value = year + '年'; month_selector.value = month + '月'; highlight_day = day; create_page(year, month); month_stuff = null; } ukui-panel-3.0.6.4/plugin-calendar/html/ukui-pt.html0000644000175000017500000000560214204636772020667 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see
DOM SEG TER QUA QUI SEX SAB
  1. 2015-02-04 星期三
  2. 4
  3. 十一月十四
  4. 甲午年【马年】
  5. 丙子月 庚辰日
ukui-panel-3.0.6.4/plugin-calendar/html/index-solar-en-mon.js0000644000175000017500000011020214204636772022346 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see 0) { scrollUp_count--; } else { scrollUp_count = 2; } } for(var index = 0; index <16; index++) { // li.children[0].children[index].innerHTML = '
'; //li.children[0].children[index].innerHTML = '
'+ list[index]+ '月'; li.children[0].children[index].innerHTML =''+ list[index] + ''; // li.children[0].children[index].innerHTML = list[index]+ '月'; // document.getElementsByTagName('span').style="float:left;width:250px;background:#6C3;"; if(index >= bind_click_position) { if(scrollUp_count%3 ===2) { if(bind_click_count < 8) { li.children[0].children[index].style.color = "#FFFFFFFF"; li.children[0].children[index].addEventListener('click', new_month_selected); bind_click_count = bind_click_count + 1; } else { li.children[0].children[index].style.color = "#FFFFFF33"; li.children[0].children[index].addEventListener('click', new_month_selected_add); } continue; } if(bind_click_count < 12) // max bind _count of month click is no more than 12 { li.children[0].children[index].style.color = "#FFFFFFFF"; li.children[0].children[index].addEventListener('click', new_month_selected); bind_click_count = bind_click_count + 1; } else { li.children[0].children[index].style.color = "#FFFFFF33"; li.children[0].children[index].addEventListener('click', new_month_selected_add); } } else { li.children[0].children[index].style.color = "#FFFFFF33"; li.children[0].children[index].addEventListener('click', new_month_selected_minus); } } } function new_month_selected_add() { if (this.parentNode.className=== 'show_months') { var str = this.innerHTML.replace("",""); month_selector.value = str.replace("",""); document.getElementById('month_div').className = 'hidden_div'; calendar.style.display = ""; year = parseInt(year_selector.value); year++; year_selector.value = year + '年'; selected_date_div.innerHTML = year_selector.value + month_selector.value; create_page(parseInt(year_selector.value), parseInt(month_selector.value)); year--; } } function new_month_selected_minus() { if (this.parentNode.className=== 'show_months') { var str = this.innerHTML.replace("",""); month_selector.value = str.replace("",""); document.getElementById('month_div').className = 'hidden_div'; calendar.style.display = ""; year = parseInt(year_selector.value); year--; year_selector.value = year + '年'; selected_date_div.innerHTML = year_selector.value + month_selector.value; create_page(parseInt(year_selector.value), parseInt(month_selector.value)); year++; } } function update_year_month_ui() { var li = document.getElementById('year_div'); for (var index = 0; index < 16; index++) { // li.children[0].children[index].innerHTML = '
'; var curretYear = year + index; li.children[0].children[index].innerHTML= ''+curretYear +'' ; //li.children[0].children[index].innerHTML= '
'+curretYear+ '年'; // if(index === 0) // { // li.children[0].children[index].style.backgroundColor = "#2b87a8"; // } li.children[0].children[index].addEventListener('click', new_month_selected); // new year implies new month // year_list.appendChild(li); // if (index === year) { // year_selector.value = index + '年'; // } } li = document.getElementById('month_div'); for (var index = 0; index < 16; index++) { li.children[0].children[index].removeEventListener('click', new_month_selected); li.children[0].children[index].style.color = "#FFFFFFFF"; if(index >=12) { var newIndex = index -12 + 1; li.children[0].children[index].style.color = "#FFFFFF33"; //li.children[0].children[index].innerHTML = '
' + new_index + '月'; li.children[0].children[index].innerHTML= ''+newIndex +'' ; //li.children[0].children[index].innerHTML = "1月"; } else { var newIndex = index + 1; //li.children[0].children[index].innerHTML ='
' + newIndex+ '月'; li.children[0].children[index].innerHTML =''+ newIndex + '' ; } if(index < 12) { li.children[0].children[index].addEventListener('click', new_month_selected); } else { li.children[0].children[index].addEventListener('click', new_month_selected_add); } // month_list.appendChild(li); if (index === month + 1) { month_selector.value = index; } } } function updateUi() { year_selector.value = year; update_year_month_ui(); // var li = document.getElementById('year_div'); // for (var index = 0; index < 16; index++) { // li.children[0].children[index].innerHTML= year + index + '年'; // li.children[0].children[index].addEventListener('click', new_month_selected); // new year implies new month // // year_list.appendChild(li); // // if (index === year) { // // year_selector.value = index + '年'; // // } // } // li = document.getElementById('month_div'); // for (var index = 0; index < 16; index++) { // if(index >=12) // { // var new_index = index -12; // li.children[0].children[index].innerHTML = new_index +1+ '月'; // } // else // { // li.children[0].children[index].innerHTML = index +1+ '月'; // } // li.children[0].children[index].addEventListener('click', new_month_selected); // // month_list.appendChild(li); // if (index === month + 1) { // month_selector.value = index + '月'; // } // } } function scroll_div(event) { var e = event||window.event; if(e.wheelDelta > 0) { if(this.id === 'year_div') { year = year - 4; } else if(this.id === 'month_div') { scrollUp_count++; update_month_ui(0); return; } } else { if(this.id === 'year_div') { year = year + 4; } else if(this.id === 'month_div') { scrollDown_count++; update_month_ui(1); return; } } updateUi(); } function update_yiji_area() { "use strict"; var year = parseInt(year_selector.value, 10); var month = parseInt(month_selector.value, 10); var hl_table = document.getElementById('hl_table'); var current_row; var current_cell; if (year !== parseInt(hl_script.id, 10)) { load_hl_script(year); return; } if (typeof HuangLi['y' + year] === 'undefined') { for (var row = 0; row < 2; row++) { if (hl_table.rows.length === row) { current_row = hl_table.insertRow(row); } else { current_row = hl_table.rows[row]; } for (var column = 1; column < 5; column++) { if (current_row.cells.length === column) { current_cell = current_row.insertCell(column); } else { current_cell = current_row.cells[column]; } if (row === 1) { current_cell.innerHTML = ''; } else { current_cell.innerHTML = ''; } } } } var day = highlight_day; var month_str = month.toString(); var day_str = day.toString(); if (month <= 9) { month_str = '0' + month; } if (day <= 9) { day_str = '0' + day; } var yi_str = HuangLi['y' + year]['d' + month_str + day_str]['y']; var ji_str = HuangLi['y' + year]['d' + month_str + day_str]['j']; var hl_yi_data = yi_str.split('.'); var hl_ji_data = ji_str.split('.'); for (var row = 0; row < 2; row++) { if (hl_table.rows.length === row) { current_row = hl_table.insertRow(row); } else { current_row = hl_table.rows[row]; } for (var column = 1; column < 5; column++) { if (current_row.cells.length === column) { current_cell = current_row.insertCell(column); } else { current_cell = current_row.cells[column]; } if(0 == row ) { if(hl_yi_data[column-1]) { current_cell.innerHTML = hl_yi_data[column-1]; } else { current_cell.innerHTML = ''; } } else { if(hl_ji_data[column-1]) { current_cell.innerHTML = hl_ji_data[column-1]; } else { current_cell.innerHTML =''; } } } } } function load_hl_script(year) { "use strict"; if (hl_script) { document.body.removeChild(hl_script); hl_script = null; } hl_script = document.createElement("SCRIPT"); hl_script.type = "text/javascript"; hl_script.src = "hl/hl" + year + '.js'; hl_script.id = year; hl_script.onload = function() { update_yiji_area(); }; document.body.appendChild(hl_script); } window.onload = function () { "use strict"; load_hl_script(today.getFullYear()); // var year_list = document.getElementById('year_list'); // var month_list = document.getElementById('month_list'); year = today.getFullYear(); month = today.getMonth(); var real_month = month + 1; selected_date_div = document.getElementById('selected_date_div'); year_selector = document.createElement('year_selector'); month_selector = document.createElement('month_selector'); year_selector.value = year; month_selector.value = real_month; selected_date_div.innerHTML = year_selector.value +'.'+month_selector.value; // year_selector = document.getElementById('year_selector'); // // year_selector.addEventListener('click', popup_div); // month_selector = document.getElementById('month_selector'); // month_selector.addEventListener('click', popup_div); //end // alert("begin"); year_button = document.getElementById('year_button'); year_button.addEventListener('click', popup_div); // alert("end"); month_button= document.getElementById('month_button'); month_button.addEventListener('click', popup_div); document.getElementById('year_div').addEventListener('mousewheel',scroll_div); document.getElementById('month_div').addEventListener('mousewheel',scroll_div); document.addEventListener('click', function(event) { }); updateUi(); var goto_arrows = document.getElementsByTagName('input'); var n_months = (year_range['high'] - year_range['low'] + 1) * 12; for (var index = 0; index < goto_arrows.length; index++) { goto_arrows[index].addEventListener('click', function() { var year = parseInt(year_selector.value); var month = parseInt(month_selector.value); if(PrevClick != null) { PrevClick.style.border = "none"; PrevClick = null; } //page the year ui if(document.getElementById('year_div').className ==='visible_div') { var li = document.getElementById('year_div'); if(this.id === 'go_prev_month') { year = year -16; year_selector.value = year; // selected_date_div.innerHTML = year_selector.value + month_selector.value; for (var index = 0; index < 16; index++) { // li.children[0].children[index].innerHTML = '
'; var currentYear = year + index; //li.children[0].children[index].innerHTML= '
' + curretYear + '年'; li.children[0].children[index].innerHTML =''+ currentYear + ''; li.children[0].children[index].addEventListener('click', new_month_selected); // new year implies new month } } else if(this.id === 'go_next_month') { year = year + 16; year_selector.value = year; // selected_date_div.innerHTML = year_selector.value + month_selector.value; for (var index = 0; index < 16; index++) { // li.children[0].children[index].innerHTML = '
'; var currentYear = year + index; //li.children[0].children[index].innerHTML= '
'+ curretYear + '年'; li.children[0].children[index].innerHTML =''+ currentYear + ''; li.children[0].children[index].addEventListener('click', new_month_selected); // new year implies new month } } return; } else if(document.getElementById('month_div').className ==='visible_div')//page the month ui { if(this.id === 'go_prev_month') { year --; year_selector.value = year; selected_date_div.innerHTML = year_selector.value + '.' +month_selector.value; } else if(this.id === 'go_next_month') { year++; year_selector.value = year; selected_date_div.innerHTML = year_selector.value + '.' + month_selector.value; } return; } // var year = parseInt(year_selector.value); // var month = parseInt(month_selector.value); var month_offset = (year - year_range['low']) * 12 + month - 1; // [0, n_months - 1] if (this.id === 'go_prev_year') { month_offset -= 12; } else if (this.id === 'go_next_year') { month_offset += 12; } else if (this.id === 'go_prev_month') { month_offset -= 1; } else if (this.id === 'go_next_month') { month_offset += 1; } else { return; } if (month_offset < 0 || month_offset > n_months - 1) { return; } year_selector.value = Math.floor(month_offset / 12) + year_range['low']; month_selector.value = month_offset % 12 === 0 ? 1 : month_offset % 12 + 1; selected_date_div.innerHTML = year_selector.value + '.' +month_selector.value; create_page(parseInt(year_selector.value), parseInt(month_selector.value)); }); } var holidays = ['元旦节', '春节', '清明节', '劳动节', '端午节', '中秋节', '国庆节']; var holiday_list = document.getElementById('holiday_list'); for (var index = 0; index < holidays.length; index++) { var li = document.createElement('LI'); li.innerHTML = holidays[index]; li.addEventListener('click', go_to_holiday); holiday_list.appendChild(li); } //var holiday_button = document.getElementById('holiday_button'); //holiday_button.addEventListener('click', popup_div); var today_button = document.getElementById('today_button'); today_button.addEventListener('click', function() { year_selector.value = today.getFullYear(); month_selector.value = today.getMonth() + 1; selected_date_div.innerHTML = year_selector.value + '.' + month_selector.value; highlight_day = today.getDate(); convertToNormal(); year = today.getFullYear(); month = today.getMonth(); if(PrevClick != null) { PrevClick.style.border = "none"; PrevClick = null; } create_page(today.getFullYear(), today.getMonth() + 1); update_year_month_ui(); var header_id=document.getElementById("header"); var header_color=header_id.style.background; var x=document.getElementsByClassName("day_today"); var i; if (header_color == "rgb(0, 0, 0)"){ for (i = 0; i < x.length; i++) { x[i].style.backgroundColor = "#3593b5"; } } else{ for (i = 0; i < x.length; i++) { x[i].style.backgroundColor = header_color; } } }); calendar = document.getElementById('calendar_table'); create_page(parseInt(year_selector.value), parseInt(month_selector.value)); } function create_page(year, month) { if (year < year_range['low'] || year > year_range['high']) return; var month_stuff = LunarCalendar.calendar(year, month, true,1); highlight_day = highlight_day > month_stuff['monthDays'] ? month_stuff['monthDays'] : highlight_day; var current_row = null; var current_cell = null; for (var row = 1; row < 7; row++) { if (calendar.rows.length === row) { current_row = calendar.insertRow(row); } else { current_row = calendar.rows[row]; } for (var column = 0; column < 7; column++) { if (current_row.cells.length === column) { current_cell = current_row.insertCell(column); current_cell.addEventListener('click', function() { highlight_day = parseInt(this.children[0].innerHTML); if(PrevClick != null) { PrevClick.style.border = "none"; } this.style.border = "1px solid #7eb4ea"; PrevClick = this; if (this.className === 'day_other_month') { return; } create_page(parseInt(year_selector.value), parseInt(month_selector.value)); }); } else { current_cell = current_row.cells[column]; } var index = (row - 1) * 7 + column; // [0, 7 * 6 - 1] /* * 注意判断顺序 * 1. 表格开头/结尾的非本月日期的单元格样式与其他单元格无关,需要最先判断 * 2. 其次是‘今天’的单元格样式 * 3. 再次是当前鼠标点击选中的单元格 * 4. 再次是属于周末的单元格 * 5. 最后是其他普通单元格 */ if ((index < (month_stuff['firstDay'] -1) && month_stuff['firstDay'] != 0)//每周从周一开始,当月第一天不是星期天,上个月的日期 ||(index < 6 && month_stuff['firstDay'] === 0)//第一天是星期天 || (month_stuff['firstDay']===0 && index >= (month_stuff['monthDays'] + 6))//第一天是星期天下月的日期 ||( month_stuff['firstDay'] != 0 && index >= month_stuff['firstDay'] + month_stuff['monthDays']-1)) //第一天不是星期天下月日期 { current_cell.className = 'day_other_month'; } else if (today.getDate() === month_stuff['monthData'][index]['day'] && today.getMonth() === month - 1 && today.getFullYear() === year) { current_cell.className = 'day_today'; } else if (index === highlight_day + month_stuff['firstDay'] - 1) { current_cell.className = 'day_highlight'; } else if (column === 0 || column === 6) { current_cell.className = 'day_weekend'; } else { current_cell.className = 'day_this_month'; } var lunar_day; if (month_stuff['monthData'][index]['lunarFestival']) { lunar_day = month_stuff['monthData'][index]['lunarFestival']; // } else if (month_stuff['monthData'][index]['solarFestival']) { // lunar_day = month_stuff['monthData'][index]['solarFestival']; } else { lunar_day = month_stuff['monthData'][index]['lunarDayName']; } var worktime = null; if (month_stuff['monthData'][index]['worktime'] === 2) { worktime = document.createElement("SPAN"); worktime.className = 'worktime2'; worktime.innerHTML = ' '; } else if (month_stuff['monthData'][index]['worktime'] === 1) { worktime = document.createElement("SPAN"); worktime.className = 'worktime1'; worktime.innerHTML = ' '; } else { } /*myworktime.innerHTML = '' + month_stuff['monthData'][index]['day'] + '' + '
' + '' + lunar_day + '';*/ // if (worktime && current_cell.className !== 'day_other_month') { // //current_cell.appendChild(worktime); // //
// // document.getElementById('aa').innerHTML = worktime.innerHTML; // current_cell.innerHTML = worktime.innerHTML+ // // '
'+ // ' ' + // month_stuff['monthData'][index]['day'] + // '' + // '
' + // '' + // lunar_day + // ''; // // current_cell.innerHTML = '123' // // +'
' + '456'+ // // '
' +'789'; // } // else // { // current_cell.innerHTML = '' + // month_stuff['monthData'][index]['day'] + // '' + // '
' + // '' + // lunar_day + // ''; // } current_cell.innerHTML = '' + month_stuff['monthData'][index]['day'] + '' } } update_right_pane(year, month, highlight_day); month_stuff = null; if (header_color == "rgb(0, 0, 0)"){ var day_this_month_len=document.getElementsByClassName('day_this_month').length; for (var i=0; i",""); year_selector.value = str.replace("",""); document.getElementById('year_div').className = 'hidden_div'; calendar.style.display = ""; } else if (this.parentNode.className=== 'show_months') { var str = this.innerHTML.replace("",""); month_selector.value = str.replace("",""); document.getElementById('month_div').className = 'hidden_div'; calendar.style.display = ""; } selected_date_div.innerHTML = year_selector.value + '.' + month_selector.value; create_page(parseInt(year_selector.value), parseInt(month_selector.value)); } function popup_div(event) { var x = event.clientX - event.offsetX; var y = event.clientY - event.offsetY; var div; // TODO var width = 64; var height = 20; if (this.id === 'year_button') { div = document.getElementById('year_div'); div_range.year.x_min = x; div_range.year.x_max = x + width; div_range.year.y_min = y; div_range.year.y_max = y + height; if (div.className === 'hidden_div') { div.className = 'visible_div'; document.getElementById('month_div').className = 'hidden_div'; calendar.style.display = "none"; year = parseInt(year_selector.value); var li = document.getElementById('year_div'); year_selector.value = year + '年'; // selected_date_div.innerHTML = year_selector.value + month_selector.value; for (var index = 0; index < 16; index++) { // li.children[0].children[index].innerHTML = '
'; var currentYear = year + index; //li.children[0].children[index].innerHTML= '
' + curretYear + '年'; li.children[0].children[index].innerHTML =''+ currentYear+ '年' + ''; li.children[0].children[index].addEventListener('click', new_month_selected); // new year implies new month } } else { div.className = 'hidden_div'; calendar.style.display = ""; } } else if (this.id === 'month_button') { div = document.getElementById('month_div'); div_range.month.x_min = x; div_range.month.x_max = x + width; div_range.month.y_min = y; div_range.month.y_max = y + height; if (div.className === 'hidden_div') { div.className = 'visible_div'; document.getElementById('year_div').className = 'hidden_div'; calendar.style.display = "none"; } else { div.className = 'hidden_div'; calendar.style.display = ""; } } else { return; } // if (div.className === 'hidden_div') { // div.className = 'visible_div'; // calendar.style.display = "none"; // } else { // div.className = 'hidden_div'; // calendar.style.display = ""; // } div.style.left = x + 'px'; div.style.top = y + height + 'px'; update_year_month_ui(); //updateUi(); } function update_right_pane(year, month, day) { var month_stuff = LunarCalendar.calendar(year, month, true, 1); var general_datetime_list = document.getElementById('general_datetime_list'); var datetime_container = document.getElementById('datetime_container'); var highlight_index = month_stuff['firstDay'] + day - 1; var lunar_month_name = month_stuff['monthData'][highlight_index]['lunarMonthName']; var lunar_day_name = month_stuff['monthData'][highlight_index]['lunarDayName']; var ganzhi_year = month_stuff['monthData'][highlight_index]['GanZhiYear']; var ganzhi_month = month_stuff['monthData'][highlight_index]['GanZhiMonth']; var ganzhi_day = month_stuff['monthData'][highlight_index]['GanZhiDay']; var zodiac = month_stuff['monthData'][highlight_index]['zodiac']; var weekday = weekdays[highlight_index % 7]; console.log(highlight_index); var month_str = month.toString(); if (month <= 9) { month_str = '0' + month; } var day_str = day.toString(); if (day <= 9) { day_str = '0' + day; } if(NeedChangeCurrentTime) { datetime_container.children[1].innerHTML = year + '-' + month_str + '-' + day_str + ' ' + weekday /* + ' '+lunar_month_name + lunar_day_name*/; NeedChangeCurrentTime = 0; } /* general_datetime_list.children[0].innerHTML = year + '-' + month_str + '-' + day_str + ' 星期' + weekday; general_datetime_list.children[1].innerHTML = day_str; // e.g. 06 general_datetime_list.children[2].innerHTML = lunar_month_name + lunar_day_name;*/ //general_datetime_list.children[0].innerHTML = ganzhi_year + '年' + '【' + zodiac + '年' + '】' + ganzhi_month + '月 ' + ganzhi_day + '日'; // general_datetime_list.children[1].innerHTML = ganzhi_month + '月 ' + ganzhi_day + '日'; updateTime(); update_yiji_area(); month_stuff = null; } /* 节日查找从当月开始往后查找,包括公历节日、农历节日和农历节气,最多只查找到下一年 */ function go_to_holiday () { var year = today.getFullYear(); var month = today.getMonth() + 1; var day = 0; var month_stuff = LunarCalendar.calendar(year, month, false, 1); var found = false; var target = this.innerHTML; do { for (var index = 0; index < month_stuff['monthDays']; index++) { if (target.indexOf(month_stuff['monthData'][index]['solarFestival']) >= 0 || target.indexOf(month_stuff['monthData'][index]['lunarFestival']) >= 0 || target.indexOf(month_stuff['monthData'][index]['term']) >= 0) { day = index + 1; found = true; break; } } if (found) { break; } if (month === 12) { year++; month = 1; } else { month++; } month_stuff = LunarCalendar.calendar(year, month, false, 1); } while (year - today.getFullYear() <= 1); if (!found) { return; } year_selector.value = year; month_selector.value = month; highlight_day = day; create_page(year, month); month_stuff = null; } ukui-panel-3.0.6.4/plugin-calendar/html/ukui-mon-min.html0000644000175000017500000001521314204636772021615 0ustar fengfeng

12:42:53

2020年1月1日 星期三 腊月初七

2020年3月
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
  1. 甲午年【马年】丙子月 庚辰日
宜忌
ukui-panel-3.0.6.4/plugin-calendar/html/ukui.html0000644000175000017500000001520314204636772020244 0ustar fengfeng

12:42:53

2020年1月1日 星期三 腊月初七

2020年3月
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
  1. 甲午年【马年】丙子月 庚辰日
宜忌
ukui-panel-3.0.6.4/plugin-calendar/html/index-pt.js0000644000175000017500000004136114204636772020473 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see div_range.year.x_max || x < div_range.year.x_min || y > div_range.year.y_max || y < div_range.year.y_min) { year_div.className = 'hidden_div'; } } if (month_div.className === 'visible_div') { if (x > div_range.month.x_max || x < div_range.month.x_min || y > div_range.month.y_max || y < div_range.month.y_min ) { month_div.className = 'hidden_div'; } } /* if (holiday_div.className === 'visible_div') { if (x > div_range.holiday.x_max || x < div_range.holiday.x_min || y > div_range.holiday.y_max || y < div_range.holiday.y_min ) { holiday_div.className = 'hidden_div'; } }*/ }); for (var index = year_range['low']; index <= year_range['high']; index++) { var li = document.createElement('LI'); li.innerHTML = index; li.addEventListener('click', new_month_selected); // new year implies new month year_list.appendChild(li); if (index === year) { year_selector.value = index; } } for (var index = 1; index <= 12; index++) { var li = document.createElement('LI'); li.innerHTML = index; li.addEventListener('click', new_month_selected); month_list.appendChild(li); if (index === month + 1) { month_selector.value = index; } } var goto_arrows = document.getElementsByTagName('input'); var n_months = (year_range['high'] - year_range['low'] + 1) * 12; for (var index = 0; index < goto_arrows.length; index++) { goto_arrows[index].addEventListener('click', function() { var year = parseInt(year_selector.value); var month = parseInt(month_selector.value); var month_offset = (year - year_range['low']) * 12 + month - 1; // [0, n_months - 1] if (this.id === 'go_prev_year') { month_offset -= 12; } else if (this.id === 'go_next_year') { month_offset += 12; } else if (this.id === 'go_prev_month') { month_offset -= 1; } else if (this.id === 'go_next_month') { month_offset += 1; } else { return; } if (month_offset < 0 || month_offset > n_months - 1) { return; } year_selector.value = Math.floor(month_offset / 12) + year_range['low']; month_selector.value = month_offset % 12 === 0 ? 1 : month_offset % 12 + 1; create_page(parseInt(year_selector.value), parseInt(month_selector.value)); }); } /* var holidays = ['元旦节', '春节', '清明节', '劳动节', '端午节', '中秋节', '国庆节']; var holiday_list = document.getElementById('holiday_list'); for (var index = 0; index < holidays.length; index++) { var li = document.createElement('LI'); li.innerHTML = holidays[index]; li.addEventListener('click', go_to_holiday); holiday_list.appendChild(li); }*/ // var holiday_button = document.getElementById('holiday_button'); // holiday_button.addEventListener('click', popup_div); var today_button = document.getElementById('today_button'); today_button.addEventListener('click', function() { year_selector.value = today.getFullYear(); month_selector.value = today.getMonth() + 1; highlight_day = today.getDate(); create_page(today.getFullYear(), today.getMonth() + 1); }); calendar = document.getElementById('calendar_table'); create_page(parseInt(year_selector.value), parseInt(month_selector.value)); } function create_page(year, month) { if (year < year_range['low'] || year > year_range['high']) return; var month_stuff = LunarCalendar.calendar(year, month, true); highlight_day = highlight_day > month_stuff['monthDays'] ? month_stuff['monthDays'] : highlight_day; var current_row = null; var current_cell = null; for (var row = 1; row < 7; row++) { if (calendar.rows.length === row) { current_row = calendar.insertRow(row); } else { current_row = calendar.rows[row]; } for (var column = 0; column < 7; column++) { if (current_row.cells.length === column) { current_cell = current_row.insertCell(column); current_cell.addEventListener('click', function() { highlight_day = parseInt(this.children[0].innerHTML); if (this.className === 'day_other_month') { return; } create_page(parseInt(year_selector.value), parseInt(month_selector.value)); }); } else { current_cell = current_row.cells[column]; } var index = (row - 1) * 7 + column; // [0, 7 * 6 - 1] /* * 注意判断顺序 * 1. 表格开头/结尾的非本月日期的单元格样式与其他单元格无关,需要最先判断 * 2. 其次是‘今天’的单元格样式 * 3. 再次是当前鼠标点击选中的单元格 * 4. 再次是属于周末的单元格 * 5. 最后是其他普通单元格 */ if (index < month_stuff['firstDay'] || index >= month_stuff['firstDay'] + month_stuff['monthDays']) { current_cell.className = 'day_other_month'; } else if (today.getDate() === month_stuff['monthData'][index]['day'] && today.getMonth() === month - 1 && today.getFullYear() === year) { current_cell.className = 'day_today'; } else if (index === highlight_day + month_stuff['firstDay'] - 1) { current_cell.className = 'day_highlight'; } else if (column === 0 || column === 6) { current_cell.className = 'day_weekend'; } else { current_cell.className = 'day_this_month'; } var lunar_day; if (month_stuff['monthData'][index]['lunarFestival']) { lunar_day = month_stuff['monthData'][index]['lunarFestival']; // } else if (month_stuff['monthData'][index]['solarFestival']) { // lunar_day = month_stuff['monthData'][index]['solarFestival']; } else { lunar_day = month_stuff['monthData'][index]['lunarDayName']; } var worktime = null; if (month_stuff['monthData'][index]['worktime'] === 2) { // worktime = document.createElement("SPAN"); worktime.className = 'worktime2'; // worktime.innerHTML = '休'; } else if (month_stuff['monthData'][index]['worktime'] === 1) { // worktime = document.createElement("SPAN"); worktime.className = 'worktime1'; // worktime.innerHTML = '班'; } else { } current_cell.innerHTML = '' + month_stuff['monthData'][index]['day'] + '' + '
' + '' + ''; if (worktime && current_cell.className !== 'day_other_month') { // current_cell.appendChild(worktime); } } } update_right_pane(year, month, highlight_day); month_stuff = null; } function new_month_selected() { if (this.parentNode.id === 'year_list') { year_selector.value = this.innerHTML; document.getElementById('year_div').className = 'hidden_div'; } else if (this.parentNode.id === 'month_list') { month_selector.value = this.innerHTML; document.getElementById('month_div').className = 'hidden_div'; } create_page(parseInt(year_selector.value), parseInt(month_selector.value)); } function popup_div(event) { var x = event.clientX - event.offsetX; var y = event.clientY - event.offsetY; var div; // TODO var width = 64; var height = 20; if (this.id === 'year_selector') { div = document.getElementById('year_div'); div_range.year.x_min = x; div_range.year.x_max = x + width; div_range.year.y_min = y; div_range.year.y_max = y + height; } else if (this.id === 'month_selector') { div = document.getElementById('month_div'); div_range.month.x_min = x; div_range.month.x_max = x + width; div_range.month.y_min = y; div_range.month.y_max = y + height; } /* else if (this.id === 'holiday_button') { div = document.getElementById('holiday_div'); div.style.width = '64px'; div.style.height = '100px'; div_range.holiday.x_min = x; div_range.holiday.x_max = x + width; div_range.holiday.y_min = y; div_range.holiday.y_max = y + height; }*/else { return; } if (div.className === 'hidden_div') { div.className = 'visible_div'; } else { div.className = 'hidden_div'; } div.style.left = x + 'px'; div.style.top = y + height + 'px'; } function update_right_pane(year, month, day) { var month_stuff = LunarCalendar.calendar(year, month, true); var general_datetime_list = document.getElementById('general_datetime_list'); var highlight_index = month_stuff['firstDay'] + day - 1; var lunar_month_name = month_stuff['monthData'][highlight_index]['lunarMonthName']; var lunar_day_name = month_stuff['monthData'][highlight_index]['lunarDayName']; var ganzhi_year = month_stuff['monthData'][highlight_index]['GanZhiYear']; var ganzhi_month = month_stuff['monthData'][highlight_index]['GanZhiMonth']; var ganzhi_day = month_stuff['monthData'][highlight_index]['GanZhiDay']; var zodiac = month_stuff['monthData'][highlight_index]['zodiac']; var weekday = weekdays[highlight_index % 7]; var month_str = month.toString(); if (month <= 9) { month_str = '0' + month; } var day_str = day.toString(); if (day <= 9) { day_str = '0' + day; } general_datetime_list.children[0].innerHTML = month_str + '-' + day_str + '-' + year + ' ' + weekday; general_datetime_list.children[1].innerHTML = day_str; // e.g. 06 general_datetime_list.children[2].innerHTML = ' '; general_datetime_list.children[3].innerHTML = ' '; general_datetime_list.children[4].innerHTML = ' '; //update_yiji_area(); month_stuff = null; } /* 节日查找从当月开始往后查找,包括公历节日、农历节日和农历节气,最多只查找到下一年 */ /*function go_to_holiday () { var year = today.getFullYear(); var month = today.getMonth() + 1; var day = 0; var month_stuff = LunarCalendar.calendar(year, month, false); var found = false; var target = this.innerHTML; do { for (var index = 0; index < month_stuff['monthDays']; index++) { if (target.indexOf(month_stuff['monthData'][index]['solarFestival']) >= 0 || target.indexOf(month_stuff['monthData'][index]['lunarFestival']) >= 0 || target.indexOf(month_stuff['monthData'][index]['term']) >= 0) { day = index + 1; found = true; break; } } if (found) { break; } if (month === 12) { year++; month = 1; } else { month++; } month_stuff = LunarCalendar.calendar(year, month, false); } while (year - today.getFullYear() <= 1); if (!found) { return; } year_selector.value = year; month_selector.value = month + 'Month'; highlight_day = day; create_page(year, month); month_stuff = null; }*/ ukui-panel-3.0.6.4/plugin-calendar/html/index-en.js0000644000175000017500000004135214204636772020452 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see div_range.year.x_max || x < div_range.year.x_min || y > div_range.year.y_max || y < div_range.year.y_min) { year_div.className = 'hidden_div'; } } if (month_div.className === 'visible_div') { if (x > div_range.month.x_max || x < div_range.month.x_min || y > div_range.month.y_max || y < div_range.month.y_min ) { month_div.className = 'hidden_div'; } } /* if (holiday_div.className === 'visible_div') { if (x > div_range.holiday.x_max || x < div_range.holiday.x_min || y > div_range.holiday.y_max || y < div_range.holiday.y_min ) { holiday_div.className = 'hidden_div'; } }*/ }); for (var index = year_range['low']; index <= year_range['high']; index++) { var li = document.createElement('LI'); li.innerHTML = index; li.addEventListener('click', new_month_selected); // new year implies new month year_list.appendChild(li); if (index === year) { year_selector.value = index; } } for (var index = 1; index <= 12; index++) { var li = document.createElement('LI'); li.innerHTML = index; li.addEventListener('click', new_month_selected); month_list.appendChild(li); if (index === month + 1) { month_selector.value = index; } } var goto_arrows = document.getElementsByTagName('input'); var n_months = (year_range['high'] - year_range['low'] + 1) * 12; for (var index = 0; index < goto_arrows.length; index++) { goto_arrows[index].addEventListener('click', function() { var year = parseInt(year_selector.value); var month = parseInt(month_selector.value); var month_offset = (year - year_range['low']) * 12 + month - 1; // [0, n_months - 1] if (this.id === 'go_prev_year') { month_offset -= 12; } else if (this.id === 'go_next_year') { month_offset += 12; } else if (this.id === 'go_prev_month') { month_offset -= 1; } else if (this.id === 'go_next_month') { month_offset += 1; } else { return; } if (month_offset < 0 || month_offset > n_months - 1) { return; } year_selector.value = Math.floor(month_offset / 12) + year_range['low']; month_selector.value = month_offset % 12 === 0 ? 1 : month_offset % 12 + 1; create_page(parseInt(year_selector.value), parseInt(month_selector.value)); }); } /* var holidays = ['元旦节', '春节', '清明节', '劳动节', '端午节', '中秋节', '国庆节']; var holiday_list = document.getElementById('holiday_list'); for (var index = 0; index < holidays.length; index++) { var li = document.createElement('LI'); li.innerHTML = holidays[index]; li.addEventListener('click', go_to_holiday); holiday_list.appendChild(li); }*/ // var holiday_button = document.getElementById('holiday_button'); // holiday_button.addEventListener('click', popup_div); var today_button = document.getElementById('today_button'); today_button.addEventListener('click', function() { year_selector.value = today.getFullYear(); month_selector.value = today.getMonth() + 1; highlight_day = today.getDate(); create_page(today.getFullYear(), today.getMonth() + 1); }); calendar = document.getElementById('calendar_table'); create_page(parseInt(year_selector.value), parseInt(month_selector.value)); } function create_page(year, month) { if (year < year_range['low'] || year > year_range['high']) return; var month_stuff = LunarCalendar.calendar(year, month, true); highlight_day = highlight_day > month_stuff['monthDays'] ? month_stuff['monthDays'] : highlight_day; var current_row = null; var current_cell = null; for (var row = 1; row < 7; row++) { if (calendar.rows.length === row) { current_row = calendar.insertRow(row); } else { current_row = calendar.rows[row]; } for (var column = 0; column < 7; column++) { if (current_row.cells.length === column) { current_cell = current_row.insertCell(column); current_cell.addEventListener('click', function() { highlight_day = parseInt(this.children[0].innerHTML); if (this.className === 'day_other_month') { return; } create_page(parseInt(year_selector.value), parseInt(month_selector.value)); }); } else { current_cell = current_row.cells[column]; } var index = (row - 1) * 7 + column; // [0, 7 * 6 - 1] /* * 注意判断顺序 * 1. 表格开头/结尾的非本月日期的单元格样式与其他单元格无关,需要最先判断 * 2. 其次是‘今天’的单元格样式 * 3. 再次是当前鼠标点击选中的单元格 * 4. 再次是属于周末的单元格 * 5. 最后是其他普通单元格 */ if (index < month_stuff['firstDay'] || index >= month_stuff['firstDay'] + month_stuff['monthDays']) { current_cell.className = 'day_other_month'; } else if (today.getDate() === month_stuff['monthData'][index]['day'] && today.getMonth() === month - 1 && today.getFullYear() === year) { current_cell.className = 'day_today'; } else if (index === highlight_day + month_stuff['firstDay'] - 1) { current_cell.className = 'day_highlight'; } else if (column === 0 || column === 6) { current_cell.className = 'day_weekend'; } else { current_cell.className = 'day_this_month'; } var lunar_day; if (month_stuff['monthData'][index]['lunarFestival']) { lunar_day = month_stuff['monthData'][index]['lunarFestival']; // } else if (month_stuff['monthData'][index]['solarFestival']) { // lunar_day = month_stuff['monthData'][index]['solarFestival']; } else { lunar_day = month_stuff['monthData'][index]['lunarDayName']; } var worktime = null; if (month_stuff['monthData'][index]['worktime'] === 2) { // worktime = document.createElement("SPAN"); worktime.className = 'worktime2'; // worktime.innerHTML = '休'; } else if (month_stuff['monthData'][index]['worktime'] === 1) { // worktime = document.createElement("SPAN"); worktime.className = 'worktime1'; // worktime.innerHTML = '班'; } else { } current_cell.innerHTML = '' + month_stuff['monthData'][index]['day'] + '' + '
' + '' + ''; if (worktime && current_cell.className !== 'day_other_month') { // current_cell.appendChild(worktime); } } } update_right_pane(year, month, highlight_day); month_stuff = null; } function new_month_selected() { if (this.parentNode.id === 'year_list') { year_selector.value = this.innerHTML; document.getElementById('year_div').className = 'hidden_div'; } else if (this.parentNode.id === 'month_list') { month_selector.value = this.innerHTML; document.getElementById('month_div').className = 'hidden_div'; } create_page(parseInt(year_selector.value), parseInt(month_selector.value)); } function popup_div(event) { var x = event.clientX - event.offsetX; var y = event.clientY - event.offsetY; var div; // TODO var width = 64; var height = 20; if (this.id === 'year_selector') { div = document.getElementById('year_div'); div_range.year.x_min = x; div_range.year.x_max = x + width; div_range.year.y_min = y; div_range.year.y_max = y + height; } else if (this.id === 'month_selector') { div = document.getElementById('month_div'); div_range.month.x_min = x; div_range.month.x_max = x + width; div_range.month.y_min = y; div_range.month.y_max = y + height; } /* else if (this.id === 'holiday_button') { div = document.getElementById('holiday_div'); div.style.width = '64px'; div.style.height = '100px'; div_range.holiday.x_min = x; div_range.holiday.x_max = x + width; div_range.holiday.y_min = y; div_range.holiday.y_max = y + height; }*/else { return; } if (div.className === 'hidden_div') { div.className = 'visible_div'; } else { div.className = 'hidden_div'; } div.style.left = x + 'px'; div.style.top = y + height + 'px'; } function update_right_pane(year, month, day) { var month_stuff = LunarCalendar.calendar(year, month, true); var general_datetime_list = document.getElementById('general_datetime_list'); var highlight_index = month_stuff['firstDay'] + day - 1; var lunar_month_name = month_stuff['monthData'][highlight_index]['lunarMonthName']; var lunar_day_name = month_stuff['monthData'][highlight_index]['lunarDayName']; var ganzhi_year = month_stuff['monthData'][highlight_index]['GanZhiYear']; var ganzhi_month = month_stuff['monthData'][highlight_index]['GanZhiMonth']; var ganzhi_day = month_stuff['monthData'][highlight_index]['GanZhiDay']; var zodiac = month_stuff['monthData'][highlight_index]['zodiac']; var weekday = weekdays[highlight_index % 7]; var month_str = month.toString(); if (month <= 9) { month_str = '0' + month; } var day_str = day.toString(); if (day <= 9) { day_str = '0' + day; } general_datetime_list.children[0].innerHTML = month_str + '-' + day_str + '-' + year + ' ' + weekday; general_datetime_list.children[1].innerHTML = day_str; // e.g. 06 general_datetime_list.children[2].innerHTML = ' '; general_datetime_list.children[3].innerHTML = ' '; general_datetime_list.children[4].innerHTML = ' '; update_yiji_area(); month_stuff = null; } /* 节日查找从当月开始往后查找,包括公历节日、农历节日和农历节气,最多只查找到下一年 */ /*function go_to_holiday () { var year = today.getFullYear(); var month = today.getMonth() + 1; var day = 0; var month_stuff = LunarCalendar.calendar(year, month, false); var found = false; var target = this.innerHTML; do { for (var index = 0; index < month_stuff['monthDays']; index++) { if (target.indexOf(month_stuff['monthData'][index]['solarFestival']) >= 0 || target.indexOf(month_stuff['monthData'][index]['lunarFestival']) >= 0 || target.indexOf(month_stuff['monthData'][index]['term']) >= 0) { day = index + 1; found = true; break; } } if (found) { break; } if (month === 12) { year++; month = 1; } else { month++; } month_stuff = LunarCalendar.calendar(year, month, false); } while (year - today.getFullYear() <= 1); if (!found) { return; } year_selector.value = year; month_selector.value = month + 'Month'; highlight_day = day; create_page(year, month); month_stuff = null; }*/ ukui-panel-3.0.6.4/plugin-calendar/html/ukui-min.html0000644000175000017500000001520714204636772021031 0ustar fengfeng

12:42:53

2020年1月1日 星期三 腊月初七

2020年3月
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
  1. 甲午年【马年】丙子月 庚辰日
宜忌
ukui-panel-3.0.6.4/plugin-calendar/html/ukui-en.css0000644000175000017500000002402714204636772020474 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see 0) { scrollUp_count--; } else { scrollUp_count = 2; } } for(var index = 0; index <16; index++) { // li.children[0].children[index].innerHTML = '
'; //li.children[0].children[index].innerHTML = '
'+ list[index]+ '月'; li.children[0].children[index].innerHTML =''+ list[index] + ''; // li.children[0].children[index].innerHTML = list[index]+ '月'; // document.getElementsByTagName('span').style="float:left;width:250px;background:#6C3;"; if(index >= bind_click_position) { if(scrollUp_count%3 ===2) { if(bind_click_count < 8) { li.children[0].children[index].style.color = "#FFFFFFFF"; li.children[0].children[index].addEventListener('click', new_month_selected); bind_click_count = bind_click_count + 1; } else { li.children[0].children[index].style.color = "#FFFFFF33"; li.children[0].children[index].addEventListener('click', new_month_selected_add); } continue; } if(bind_click_count < 12) // max bind _count of month click is no more than 12 { li.children[0].children[index].style.color = "#FFFFFFFF"; li.children[0].children[index].addEventListener('click', new_month_selected); bind_click_count = bind_click_count + 1; } else { li.children[0].children[index].style.color = "#FFFFFF33"; li.children[0].children[index].addEventListener('click', new_month_selected_add); } } else { li.children[0].children[index].style.color = "#FFFFFF33"; li.children[0].children[index].addEventListener('click', new_month_selected_minus); } } } function new_month_selected_add() { if (this.parentNode.className=== 'show_months') { var str = this.innerHTML.replace("",""); month_selector.value = str.replace("",""); document.getElementById('month_div').className = 'hidden_div'; calendar.style.display = ""; year = parseInt(year_selector.value); year++; year_selector.value = year + '年'; selected_date_div.innerHTML = year_selector.value + month_selector.value; create_page(parseInt(year_selector.value), parseInt(month_selector.value)); year--; } } function new_month_selected_minus() { if (this.parentNode.className=== 'show_months') { var str = this.innerHTML.replace("",""); month_selector.value = str.replace("",""); document.getElementById('month_div').className = 'hidden_div'; calendar.style.display = ""; year = parseInt(year_selector.value); year--; year_selector.value = year + '年'; selected_date_div.innerHTML = year_selector.value + month_selector.value; create_page(parseInt(year_selector.value), parseInt(month_selector.value)); year++; } } function update_year_month_ui() { var li = document.getElementById('year_div'); for (var index = 0; index < 16; index++) { // li.children[0].children[index].innerHTML = '
'; var curretYear = year + index; li.children[0].children[index].innerHTML= ''+curretYear +'' ; //li.children[0].children[index].innerHTML= '
'+curretYear+ '年'; // if(index === 0) // { // li.children[0].children[index].style.backgroundColor = "#2b87a8"; // } li.children[0].children[index].addEventListener('click', new_month_selected); // new year implies new month // year_list.appendChild(li); // if (index === year) { // year_selector.value = index + '年'; // } } li = document.getElementById('month_div'); for (var index = 0; index < 16; index++) { li.children[0].children[index].removeEventListener('click', new_month_selected); li.children[0].children[index].style.color = "#FFFFFFFF"; if(index >=12) { var newIndex = index -12 + 1; li.children[0].children[index].style.color = "#FFFFFF33"; //li.children[0].children[index].innerHTML = '
' + new_index + '月'; li.children[0].children[index].innerHTML= ''+newIndex +'' ; //li.children[0].children[index].innerHTML = "1月"; } else { var newIndex = index + 1; //li.children[0].children[index].innerHTML ='
' + newIndex+ '月'; li.children[0].children[index].innerHTML =''+ newIndex + '' ; } if(index < 12) { li.children[0].children[index].addEventListener('click', new_month_selected); } else { li.children[0].children[index].addEventListener('click', new_month_selected_add); } // month_list.appendChild(li); if (index === month + 1) { month_selector.value = index; } } } function updateUi() { year_selector.value = year; update_year_month_ui(); // var li = document.getElementById('year_div'); // for (var index = 0; index < 16; index++) { // li.children[0].children[index].innerHTML= year + index + '年'; // li.children[0].children[index].addEventListener('click', new_month_selected); // new year implies new month // // year_list.appendChild(li); // // if (index === year) { // // year_selector.value = index + '年'; // // } // } // li = document.getElementById('month_div'); // for (var index = 0; index < 16; index++) { // if(index >=12) // { // var new_index = index -12; // li.children[0].children[index].innerHTML = new_index +1+ '月'; // } // else // { // li.children[0].children[index].innerHTML = index +1+ '月'; // } // li.children[0].children[index].addEventListener('click', new_month_selected); // // month_list.appendChild(li); // if (index === month + 1) { // month_selector.value = index + '月'; // } // } } function scroll_div(event) { var e = event||window.event; if(e.wheelDelta > 0) { if(this.id === 'year_div') { year = year - 4; } else if(this.id === 'month_div') { scrollUp_count++; update_month_ui(0); return; } } else { if(this.id === 'year_div') { year = year + 4; } else if(this.id === 'month_div') { scrollDown_count++; update_month_ui(1); return; } } updateUi(); } function update_yiji_area() { "use strict"; var year = parseInt(year_selector.value, 10); var month = parseInt(month_selector.value, 10); var hl_table = document.getElementById('hl_table'); var current_row; var current_cell; if (year !== parseInt(hl_script.id, 10)) { load_hl_script(year); return; } if (typeof HuangLi['y' + year] === 'undefined') { for (var row = 0; row < 2; row++) { if (hl_table.rows.length === row) { current_row = hl_table.insertRow(row); } else { current_row = hl_table.rows[row]; } for (var column = 1; column < 5; column++) { if (current_row.cells.length === column) { current_cell = current_row.insertCell(column); } else { current_cell = current_row.cells[column]; } if (row === 1) { current_cell.innerHTML = ''; } else { current_cell.innerHTML = ''; } } } } var day = highlight_day; var month_str = month.toString(); var day_str = day.toString(); if (month <= 9) { month_str = '0' + month; } if (day <= 9) { day_str = '0' + day; } var yi_str = HuangLi['y' + year]['d' + month_str + day_str]['y']; var ji_str = HuangLi['y' + year]['d' + month_str + day_str]['j']; var hl_yi_data = yi_str.split('.'); var hl_ji_data = ji_str.split('.'); for (var row = 0; row < 2; row++) { if (hl_table.rows.length === row) { current_row = hl_table.insertRow(row); } else { current_row = hl_table.rows[row]; } for (var column = 1; column < 5; column++) { if (current_row.cells.length === column) { current_cell = current_row.insertCell(column); } else { current_cell = current_row.cells[column]; } if(0 == row ) { if(hl_yi_data[column-1]) { current_cell.innerHTML = hl_yi_data[column-1]; } else { current_cell.innerHTML = ''; } } else { if(hl_ji_data[column-1]) { current_cell.innerHTML = hl_ji_data[column-1]; } else { current_cell.innerHTML =''; } } } } } function load_hl_script(year) { "use strict"; if (hl_script) { document.body.removeChild(hl_script); hl_script = null; } hl_script = document.createElement("SCRIPT"); hl_script.type = "text/javascript"; hl_script.src = "hl/hl" + year + '.js'; hl_script.id = year; hl_script.onload = function() { update_yiji_area(); }; document.body.appendChild(hl_script); } window.onload = function () { "use strict"; load_hl_script(today.getFullYear()); // var year_list = document.getElementById('year_list'); // var month_list = document.getElementById('month_list'); year = today.getFullYear(); month = today.getMonth(); var real_month = month + 1; selected_date_div = document.getElementById('selected_date_div'); year_selector = document.createElement('year_selector'); month_selector = document.createElement('month_selector'); year_selector.value = year; month_selector.value = real_month; selected_date_div.innerHTML = year_selector.value +'.'+month_selector.value; // year_selector = document.getElementById('year_selector'); // // year_selector.addEventListener('click', popup_div); // month_selector = document.getElementById('month_selector'); // month_selector.addEventListener('click', popup_div); //end // alert("begin"); year_button = document.getElementById('year_button'); year_button.addEventListener('click', popup_div); // alert("end"); month_button= document.getElementById('month_button'); month_button.addEventListener('click', popup_div); document.getElementById('year_div').addEventListener('mousewheel',scroll_div); document.getElementById('month_div').addEventListener('mousewheel',scroll_div); document.addEventListener('click', function(event) { }); updateUi(); var goto_arrows = document.getElementsByTagName('input'); var n_months = (year_range['high'] - year_range['low'] + 1) * 12; for (var index = 0; index < goto_arrows.length; index++) { goto_arrows[index].addEventListener('click', function() { var year = parseInt(year_selector.value); var month = parseInt(month_selector.value); if(PrevClick != null) { PrevClick.style.border = "none"; PrevClick = null; } //page the year ui if(document.getElementById('year_div').className ==='visible_div') { var li = document.getElementById('year_div'); if(this.id === 'go_prev_month') { year = year -16; year_selector.value = year; // selected_date_div.innerHTML = year_selector.value + month_selector.value; for (var index = 0; index < 16; index++) { // li.children[0].children[index].innerHTML = '
'; var currentYear = year + index; //li.children[0].children[index].innerHTML= '
' + curretYear + '年'; li.children[0].children[index].innerHTML =''+ currentYear + ''; li.children[0].children[index].addEventListener('click', new_month_selected); // new year implies new month } } else if(this.id === 'go_next_month') { year = year + 16; year_selector.value = year; // selected_date_div.innerHTML = year_selector.value + month_selector.value; for (var index = 0; index < 16; index++) { // li.children[0].children[index].innerHTML = '
'; var currentYear = year + index; //li.children[0].children[index].innerHTML= '
'+ curretYear + '年'; li.children[0].children[index].innerHTML =''+ currentYear + ''; li.children[0].children[index].addEventListener('click', new_month_selected); // new year implies new month } } return; } else if(document.getElementById('month_div').className ==='visible_div')//page the month ui { if(this.id === 'go_prev_month') { year --; year_selector.value = year; selected_date_div.innerHTML = year_selector.value + '.' +month_selector.value; } else if(this.id === 'go_next_month') { year++; year_selector.value = year; selected_date_div.innerHTML = year_selector.value + '.' + month_selector.value; } return; } // var year = parseInt(year_selector.value); // var month = parseInt(month_selector.value); var month_offset = (year - year_range['low']) * 12 + month - 1; // [0, n_months - 1] if (this.id === 'go_prev_year') { month_offset -= 12; } else if (this.id === 'go_next_year') { month_offset += 12; } else if (this.id === 'go_prev_month') { month_offset -= 1; } else if (this.id === 'go_next_month') { month_offset += 1; } else { return; } if (month_offset < 0 || month_offset > n_months - 1) { return; } year_selector.value = Math.floor(month_offset / 12) + year_range['low']; month_selector.value = month_offset % 12 === 0 ? 1 : month_offset % 12 + 1; selected_date_div.innerHTML = year_selector.value + '.' +month_selector.value; create_page(parseInt(year_selector.value), parseInt(month_selector.value)); }); } var holidays = ['元旦节', '春节', '清明节', '劳动节', '端午节', '中秋节', '国庆节']; var holiday_list = document.getElementById('holiday_list'); for (var index = 0; index < holidays.length; index++) { var li = document.createElement('LI'); li.innerHTML = holidays[index]; li.addEventListener('click', go_to_holiday); holiday_list.appendChild(li); } //var holiday_button = document.getElementById('holiday_button'); //holiday_button.addEventListener('click', popup_div); var today_button = document.getElementById('today_button'); today_button.addEventListener('click', function() { year_selector.value = today.getFullYear(); month_selector.value = today.getMonth() + 1; selected_date_div.innerHTML = year_selector.value + '.' + month_selector.value; highlight_day = today.getDate(); convertToNormal(); year = today.getFullYear(); month = today.getMonth(); if(PrevClick != null) { PrevClick.style.border = "none"; PrevClick = null; } create_page(today.getFullYear(), today.getMonth() + 1); update_year_month_ui(); var header_id=document.getElementById("header"); var header_color=header_id.style.background; var x=document.getElementsByClassName("day_today"); var i; if (header_color == "rgb(0, 0, 0)"){ for (i = 0; i < x.length; i++) { x[i].style.backgroundColor = "#3593b5"; } } else{ for (i = 0; i < x.length; i++) { x[i].style.backgroundColor = header_color; } } }); calendar = document.getElementById('calendar_table'); create_page(parseInt(year_selector.value), parseInt(month_selector.value)); } function create_page(year, month) { if (year < year_range['low'] || year > year_range['high']) return; var month_stuff = LunarCalendar.calendar(year, month, true,0); highlight_day = highlight_day > month_stuff['monthDays'] ? month_stuff['monthDays'] : highlight_day; var current_row = null; var current_cell = null; for (var row = 1; row < 7; row++) { if (calendar.rows.length === row) { current_row = calendar.insertRow(row); } else { current_row = calendar.rows[row]; } for (var column = 0; column < 7; column++) { if (current_row.cells.length === column) { current_cell = current_row.insertCell(column); current_cell.addEventListener('click', function() { highlight_day = parseInt(this.children[0].innerHTML); if(PrevClick != null) { PrevClick.style.border = "none"; } this.style.border = "1px solid #7eb4ea"; PrevClick = this; if (this.className === 'day_other_month') { return; } create_page(parseInt(year_selector.value), parseInt(month_selector.value)); }); } else { current_cell = current_row.cells[column]; } var index = (row - 1) * 7 + column; // [0, 7 * 6 - 1] /* * 注意判断顺序 * 1. 表格开头/结尾的非本月日期的单元格样式与其他单元格无关,需要最先判断 * 2. 其次是‘今天’的单元格样式 * 3. 再次是当前鼠标点击选中的单元格 * 4. 再次是属于周末的单元格 * 5. 最后是其他普通单元格 */ if ((index < (month_stuff['firstDay'] -1) && month_stuff['firstDay'] != 0)//每周从周一开始,当月第一天不是星期天,上个月的日期 ||(index < 6 && month_stuff['firstDay'] === 0)//第一天是星期天 || (month_stuff['firstDay']===0 && index >= (month_stuff['monthDays'] + 6))//第一天是星期天下月的日期 ||( month_stuff['firstDay'] != 0 && index >= month_stuff['firstDay'] + month_stuff['monthDays']-1)) //第一天不是星期天下月日期 { current_cell.className = 'day_other_month'; } else if (today.getDate() === month_stuff['monthData'][index]['day'] && today.getMonth() === month - 1 && today.getFullYear() === year) { current_cell.className = 'day_today'; } else if (index === highlight_day + month_stuff['firstDay'] - 1) { current_cell.className = 'day_highlight'; } else if (column === 0 || column === 6) { current_cell.className = 'day_weekend'; } else { current_cell.className = 'day_this_month'; } var lunar_day; if (month_stuff['monthData'][index]['lunarFestival']) { lunar_day = month_stuff['monthData'][index]['lunarFestival']; // } else if (month_stuff['monthData'][index]['solarFestival']) { // lunar_day = month_stuff['monthData'][index]['solarFestival']; } else { lunar_day = month_stuff['monthData'][index]['lunarDayName']; } var worktime = null; if (month_stuff['monthData'][index]['worktime'] === 2) { worktime = document.createElement("SPAN"); worktime.className = 'worktime2'; worktime.innerHTML = ' '; } else if (month_stuff['monthData'][index]['worktime'] === 1) { worktime = document.createElement("SPAN"); worktime.className = 'worktime1'; worktime.innerHTML = ' '; } else { } /*myworktime.innerHTML = '' + month_stuff['monthData'][index]['day'] + '' + '
' + '' + lunar_day + '';*/ // if (worktime && current_cell.className !== 'day_other_month') { // //current_cell.appendChild(worktime); // //
// // document.getElementById('aa').innerHTML = worktime.innerHTML; // current_cell.innerHTML = worktime.innerHTML+ // // '
'+ // ' ' + // month_stuff['monthData'][index]['day'] + // '' + // '
' + // '' + // lunar_day + // ''; // // current_cell.innerHTML = '123' // // +'
' + '456'+ // // '
' +'789'; // } // else // { // current_cell.innerHTML = '' + // month_stuff['monthData'][index]['day'] + // '' + // '
' + // '' + // lunar_day + // ''; // } current_cell.innerHTML = '' + month_stuff['monthData'][index]['day'] + '' } } update_right_pane(year, month, highlight_day); month_stuff = null; if (header_color == "rgb(0, 0, 0)"){ var day_this_month_len=document.getElementsByClassName('day_this_month').length; for (var i=0; i",""); year_selector.value = str.replace("",""); document.getElementById('year_div').className = 'hidden_div'; calendar.style.display = ""; } else if (this.parentNode.className=== 'show_months') { var str = this.innerHTML.replace("",""); month_selector.value = str.replace("",""); document.getElementById('month_div').className = 'hidden_div'; calendar.style.display = ""; } selected_date_div.innerHTML = year_selector.value + '.' + month_selector.value; create_page(parseInt(year_selector.value), parseInt(month_selector.value)); } function popup_div(event) { var x = event.clientX - event.offsetX; var y = event.clientY - event.offsetY; var div; // TODO var width = 64; var height = 20; if (this.id === 'year_button') { div = document.getElementById('year_div'); div_range.year.x_min = x; div_range.year.x_max = x + width; div_range.year.y_min = y; div_range.year.y_max = y + height; if (div.className === 'hidden_div') { div.className = 'visible_div'; document.getElementById('month_div').className = 'hidden_div'; calendar.style.display = "none"; year = parseInt(year_selector.value); var li = document.getElementById('year_div'); year_selector.value = year + '年'; // selected_date_div.innerHTML = year_selector.value + month_selector.value; for (var index = 0; index < 16; index++) { // li.children[0].children[index].innerHTML = '
'; var currentYear = year + index; //li.children[0].children[index].innerHTML= '
' + curretYear + '年'; li.children[0].children[index].innerHTML =''+ currentYear+ '年' + ''; li.children[0].children[index].addEventListener('click', new_month_selected); // new year implies new month } } else { div.className = 'hidden_div'; calendar.style.display = ""; } } else if (this.id === 'month_button') { div = document.getElementById('month_div'); div_range.month.x_min = x; div_range.month.x_max = x + width; div_range.month.y_min = y; div_range.month.y_max = y + height; if (div.className === 'hidden_div') { div.className = 'visible_div'; document.getElementById('year_div').className = 'hidden_div'; calendar.style.display = "none"; } else { div.className = 'hidden_div'; calendar.style.display = ""; } } else { return; } // if (div.className === 'hidden_div') { // div.className = 'visible_div'; // calendar.style.display = "none"; // } else { // div.className = 'hidden_div'; // calendar.style.display = ""; // } div.style.left = x + 'px'; div.style.top = y + height + 'px'; update_year_month_ui(); //updateUi(); } function update_right_pane(year, month, day) { var month_stuff = LunarCalendar.calendar(year, month, true, 0); var general_datetime_list = document.getElementById('general_datetime_list'); var datetime_container = document.getElementById('datetime_container'); var highlight_index = month_stuff['firstDay'] + day - 1; var lunar_month_name = month_stuff['monthData'][highlight_index]['lunarMonthName']; var lunar_day_name = month_stuff['monthData'][highlight_index]['lunarDayName']; var ganzhi_year = month_stuff['monthData'][highlight_index]['GanZhiYear']; var ganzhi_month = month_stuff['monthData'][highlight_index]['GanZhiMonth']; var ganzhi_day = month_stuff['monthData'][highlight_index]['GanZhiDay']; var zodiac = month_stuff['monthData'][highlight_index]['zodiac']; var weekday = weekdays[highlight_index % 7]; console.log(highlight_index); var month_str = month.toString(); if (month <= 9) { month_str = '0' + month; } var day_str = day.toString(); if (day <= 9) { day_str = '0' + day; } if(NeedChangeCurrentTime) { datetime_container.children[1].innerHTML = year + '-' + month_str + '-' + day_str + ' ' + weekday /* + ' '+lunar_month_name + lunar_day_name*/; NeedChangeCurrentTime = 0; } /* general_datetime_list.children[0].innerHTML = year + '-' + month_str + '-' + day_str + ' 星期' + weekday; general_datetime_list.children[1].innerHTML = day_str; // e.g. 06 general_datetime_list.children[2].innerHTML = lunar_month_name + lunar_day_name;*/ //general_datetime_list.children[0].innerHTML = ganzhi_year + '年' + '【' + zodiac + '年' + '】' + ganzhi_month + '月 ' + ganzhi_day + '日'; // general_datetime_list.children[1].innerHTML = ganzhi_month + '月 ' + ganzhi_day + '日'; updateTime(); update_yiji_area(); month_stuff = null; } /* 节日查找从当月开始往后查找,包括公历节日、农历节日和农历节气,最多只查找到下一年 */ function go_to_holiday () { var year = today.getFullYear(); var month = today.getMonth() + 1; var day = 0; var month_stuff = LunarCalendar.calendar(year, month, false, 0); var found = false; var target = this.innerHTML; do { for (var index = 0; index < month_stuff['monthDays']; index++) { if (target.indexOf(month_stuff['monthData'][index]['solarFestival']) >= 0 || target.indexOf(month_stuff['monthData'][index]['lunarFestival']) >= 0 || target.indexOf(month_stuff['monthData'][index]['term']) >= 0) { day = index + 1; found = true; break; } } if (found) { break; } if (month === 12) { year++; month = 1; } else { month++; } month_stuff = LunarCalendar.calendar(year, month, false, 0); } while (year - today.getFullYear() <= 1); if (!found) { return; } year_selector.value = year; month_selector.value = month; highlight_day = day; create_page(year, month); month_stuff = null; } ukui-panel-3.0.6.4/plugin-calendar/html/index-mon.js0000644000175000017500000014312014204636772020635 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see 0) { scrollUp_count--; } else { scrollUp_count = 2; } } for(var index = 0; index <16; index++) { // li.children[0].children[index].innerHTML = '
'; //li.children[0].children[index].innerHTML = '
'+ list[index]+ '月'; li.children[0].children[index].innerHTML =''+ list[index]+ '月' + ''; // li.children[0].children[index].innerHTML = list[index]+ '月'; // document.getElementsByTagName('span').style="float:left;width:250px;background:#6C3;"; if(index >= bind_click_position) { if(scrollUp_count%3 ===2) { if(bind_click_count < 8) { li.children[0].children[index].style.color = "#FFFFFFFF"; li.children[0].children[index].addEventListener('click', new_month_selected); bind_click_count = bind_click_count + 1; } else { li.children[0].children[index].style.color = "#FFFFFF33"; li.children[0].children[index].addEventListener('click', new_month_selected_add); } continue; } if(bind_click_count < 12) // max bind _count of month click is no more than 12 { li.children[0].children[index].style.color = "#FFFFFFFF"; li.children[0].children[index].addEventListener('click', new_month_selected); bind_click_count = bind_click_count + 1; } else { li.children[0].children[index].style.color = "#FFFFFF33"; li.children[0].children[index].addEventListener('click', new_month_selected_add); } } else { li.children[0].children[index].style.color = "#FFFFFF33"; li.children[0].children[index].addEventListener('click', new_month_selected_minus); } } } function new_month_selected_add() { if (this.parentNode.className=== 'show_months') { var str = this.innerHTML.replace("",""); month_selector.value = str.replace("",""); document.getElementById('month_div').className = 'hidden_div'; calendar.style.display = ""; year = parseInt(year_selector.value); year++; year_selector.value = year + '年'; selected_date_div.innerHTML = year_selector.value + month_selector.value; create_page(parseInt(year_selector.value), parseInt(month_selector.value)); year--; } } function new_month_selected_minus() { if (this.parentNode.className=== 'show_months') { var str = this.innerHTML.replace("",""); month_selector.value = str.replace("",""); document.getElementById('month_div').className = 'hidden_div'; calendar.style.display = ""; year = parseInt(year_selector.value); year--; year_selector.value = year + '年'; selected_date_div.innerHTML = year_selector.value + month_selector.value; create_page(parseInt(year_selector.value), parseInt(month_selector.value)); year++; } } function update_year_month_ui() { var li = document.getElementById('year_div'); for (var index = 0; index < 16; index++) { // li.children[0].children[index].innerHTML = '
'; var curretYear = year + index; li.children[0].children[index].innerHTML= ''+curretYear+ '年' +'' ; //li.children[0].children[index].innerHTML= '
'+curretYear+ '年'; // if(index === 0) // { // li.children[0].children[index].style.backgroundColor = "#2b87a8"; // } li.children[0].children[index].addEventListener('click', new_month_selected); // new year implies new month // year_list.appendChild(li); // if (index === year) { // year_selector.value = index + '年'; // } } li = document.getElementById('month_div'); for (var index = 0; index < 16; index++) { li.children[0].children[index].removeEventListener('click', new_month_selected); li.children[0].children[index].style.color = "#FFFFFFFF"; if(index >=12) { var newIndex = index -12 + 1; li.children[0].children[index].style.color = "#FFFFFF33"; //li.children[0].children[index].innerHTML = '
' + new_index + '月'; li.children[0].children[index].innerHTML= ''+newIndex + '月' +'' ; //li.children[0].children[index].innerHTML = "1月"; } else { var newIndex = index + 1; //li.children[0].children[index].innerHTML ='
' + newIndex+ '月'; li.children[0].children[index].innerHTML =''+ newIndex+ '月' + '' ; } if(index < 12) { li.children[0].children[index].addEventListener('click', new_month_selected); } else { li.children[0].children[index].addEventListener('click', new_month_selected_add); } // month_list.appendChild(li); if (index === month + 1) { month_selector.value = index + '月'; } } } function updateUi() { year_selector.value = year + '年'; update_year_month_ui(); // var li = document.getElementById('year_div'); // for (var index = 0; index < 16; index++) { // li.children[0].children[index].innerHTML= year + index + '年'; // li.children[0].children[index].addEventListener('click', new_month_selected); // new year implies new month // // year_list.appendChild(li); // // if (index === year) { // // year_selector.value = index + '年'; // // } // } // li = document.getElementById('month_div'); // for (var index = 0; index < 16; index++) { // if(index >=12) // { // var new_index = index -12; // li.children[0].children[index].innerHTML = new_index +1+ '月'; // } // else // { // li.children[0].children[index].innerHTML = index +1+ '月'; // } // li.children[0].children[index].addEventListener('click', new_month_selected); // // month_list.appendChild(li); // if (index === month + 1) { // month_selector.value = index + '月'; // } // } } function scroll_div(event) { var e = event||window.event; if(e.wheelDelta > 0) { if(this.id === 'year_div') { year = year - 4; } else if(this.id === 'month_div') { scrollUp_count++; update_month_ui(0); return; } } else { if(this.id === 'year_div') { year = year + 4; } else if(this.id === 'month_div') { scrollDown_count++; update_month_ui(1); return; } } updateUi(); } function update_yiji_area_by_date(cur_year,cur_month) { "use strict"; var year = cur_year; var month = cur_month; var hl_table = document.getElementById('hl_table'); var current_row; var current_cell; if (year !== parseInt(hl_script.id, 10)) { load_hl_script(year); return; } if (typeof HuangLi['y' + year] === 'undefined') { for (var row = 0; row < 2; row++) { if (hl_table.rows.length === row) { current_row = hl_table.insertRow(row); } else { current_row = hl_table.rows[row]; } for (var column = 1; column < 5; column++) { if (current_row.cells.length === column) { current_cell = current_row.insertCell(column); } else { current_cell = current_row.cells[column]; } if (row === 1) { current_cell.innerHTML = '无数据'; } else { current_cell.innerHTML = ''; } } } } var day = highlight_day; var month_str = month.toString(); var day_str = day.toString(); if (month <= 9) { month_str = '0' + month; } if (day <= 9) { day_str = '0' + day; } var yi_str = HuangLi['y' + year]['d' + month_str + day_str]['y']; var ji_str = HuangLi['y' + year]['d' + month_str + day_str]['j']; var hl_yi_data = yi_str.split('.'); var hl_ji_data = ji_str.split('.'); for (var row = 0; row < 2; row++) { if (hl_table.rows.length === row) { current_row = hl_table.insertRow(row); } else { current_row = hl_table.rows[row]; } for (var column = 1; column < 5; column++) { if (current_row.cells.length === column) { current_cell = current_row.insertCell(column); } else { current_cell = current_row.cells[column]; } if(0 == row ) { if(hl_yi_data[column-1]) { current_cell.innerHTML = hl_yi_data[column-1]; } else { current_cell.innerHTML = ''; } } else { if(hl_ji_data[column-1]) { current_cell.innerHTML = hl_ji_data[column-1]; } else { current_cell.innerHTML =''; } } } } } function update_yiji_area() { "use strict"; var year = parseInt(year_selector.value, 10); var month = parseInt(month_selector.value, 10); var hl_table = document.getElementById('hl_table'); var current_row; var current_cell; if (year !== parseInt(hl_script.id, 10)) { load_hl_script(year); return; } if (typeof HuangLi['y' + year] === 'undefined') { for (var row = 0; row < 2; row++) { if (hl_table.rows.length === row) { current_row = hl_table.insertRow(row); } else { current_row = hl_table.rows[row]; } for (var column = 1; column < 5; column++) { if (current_row.cells.length === column) { current_cell = current_row.insertCell(column); } else { current_cell = current_row.cells[column]; } if (row === 1) { current_cell.innerHTML = '无数据'; } else { current_cell.innerHTML = ''; } } } } var day = highlight_day; var month_str = month.toString(); var day_str = day.toString(); if (month <= 9) { month_str = '0' + month; } if (day <= 9) { day_str = '0' + day; } var yi_str = HuangLi['y' + year]['d' + month_str + day_str]['y']; var ji_str = HuangLi['y' + year]['d' + month_str + day_str]['j']; var hl_yi_data = yi_str.split('.'); var hl_ji_data = ji_str.split('.'); for (var row = 0; row < 2; row++) { if (hl_table.rows.length === row) { current_row = hl_table.insertRow(row); } else { current_row = hl_table.rows[row]; } for (var column = 1; column < 5; column++) { if (current_row.cells.length === column) { current_cell = current_row.insertCell(column); } else { current_cell = current_row.cells[column]; } if(0 == row ) { if(hl_yi_data[column-1]) { current_cell.innerHTML = hl_yi_data[column-1]; } else { current_cell.innerHTML = ''; } } else { if(hl_ji_data[column-1]) { current_cell.innerHTML = hl_ji_data[column-1]; } else { current_cell.innerHTML =''; } } } } } function load_hl_script(year) { "use strict"; if (hl_script) { document.body.removeChild(hl_script); hl_script = null; } hl_script = document.createElement("SCRIPT"); hl_script.type = "text/javascript"; hl_script.src = "hl/hl" + year + '.js'; hl_script.id = year; hl_script.onload = function() { update_yiji_area(); }; document.body.appendChild(hl_script); } window.onload = function () { var checkbox = document.getElementById('advice_checkbox'); if (localStorage.getItem('hl_table') == "display"){ checkbox.setAttribute("checked", true); hl_table.setAttribute("style", "visibility:display"); //var zodiac_icon = document.getElementById('zodiac_icon'); //zodiac_icon.setAttribute("style", "display:none"); } checkbox.onclick = function(){ console.log("checkbox triggerd"); if(this.checked){ var hl_table = document.getElementById('hl_table'); hl_table.setAttribute("style", "visibility:display"); //var zodiac_icon = document.getElementById('zodiac_icon'); //zodiac_icon.setAttribute("style", "display:none"); localStorage.setItem('hl_table', "display"); } else{ var hl_table = document.getElementById('hl_table'); hl_table.setAttribute("style", "visibility:hidden"); // var zodiac_icon = document.getElementById('zodiac_icon'); // zodiac_icon.setAttribute("style", "display:block"); //zodiac_icon.setAttribute("style", "padding-top: 33px"); localStorage.setItem('hl_table', "hidden"); } } "use strict"; load_hl_script(today.getFullYear()); // var year_list = document.getElementById('year_list'); // var month_list = document.getElementById('month_list'); year = today.getFullYear(); month = today.getMonth(); var real_month = month + 1; selected_date_div = document.getElementById('selected_date_div'); year_selector = document.createElement('year_selector'); month_selector = document.createElement('month_selector'); year_selector.value = year + '年'; month_selector.value = real_month +'月'; selected_date_div.innerHTML = year_selector.value + month_selector.value; // year_selector = document.getElementById('year_selector'); // // year_selector.addEventListener('click', popup_div); // month_selector = document.getElementById('month_selector'); // month_selector.addEventListener('click', popup_div); //end // alert("begin"); year_button = document.getElementById('year_button'); year_button.addEventListener('click', popup_div); // alert("end"); month_button= document.getElementById('month_button'); month_button.addEventListener('click', popup_div); document.getElementById('year_div').addEventListener('mousewheel',scroll_div); document.getElementById('month_div').addEventListener('mousewheel',scroll_div); // year_button = document.getElementById('year_button'); // year_button.addEventListener('click', popup_div); // month_button = document.getElementById('month_button'); // month_button.addEventListener('click', popup_div); // document.addEventListener('mousewheel', function(event) // { // //alert("sroll??"); // }) document.addEventListener('click', function(event) { // var year_div = document.getElementById('year_div'); // var month_div = document.getElementById('month_div'); // var holiday_div = document.getElementById('holiday_div'); // var x = event.clientX; // var y = event.clientY; // if (year_div.className === 'visible_div') { // if (x > div_range.year.x_max || x < div_range.year.x_min || // y > div_range.year.y_max || y < div_range.year.y_min) { // year_div.className = 'hidden_div'; // } // } // if (month_div.className === 'visible_div') { // if (x > div_range.month.x_max || x < div_range.month.x_min || // y > div_range.month.y_max || y < div_range.month.y_min ) { // month_div.className = 'hidden_div'; // } // } // if (holiday_div.className === 'visible_div') { // if (x > div_range.holiday.x_max || x < div_range.holiday.x_min || // y > div_range.holiday.y_max || y < div_range.holiday.y_min ) { // holiday_div.className = 'hidden_div'; // } // } // var header_id=document.getElementById("header"); // var header_color=header_id.style.background; // var x=document.getElementsByClassName("day_highlight"); // if (header_color == "rgb(0, 0, 0)"){ // for (i = 0; i < x.length; i++) { // x[i].style.backgroundColor = "#2b87a8"; // } // var day_highlight_len=document.getElementsByClassName('day_highlight').length; // for (var i=0; i'; li.children[0].children[index].addEventListener('click', new_month_selected); // new year implies new month } } else if(this.id === 'go_next_month') { year = year + 16; year_selector.value = year + '年'; // selected_date_div.innerHTML = year_selector.value + month_selector.value; for (var index = 0; index < 16; index++) { // li.children[0].children[index].innerHTML = '
'; var currentYear = year + index; //li.children[0].children[index].innerHTML= '
'+ curretYear + '年'; li.children[0].children[index].innerHTML =''+ currentYear+ '年' + ''; li.children[0].children[index].addEventListener('click', new_month_selected); // new year implies new month } } return; } else if(document.getElementById('month_div').className ==='visible_div')//page the month ui { if(this.id === 'go_prev_month') { year --; year_selector.value = year + '年'; selected_date_div.innerHTML = year_selector.value + month_selector.value; } else if(this.id === 'go_next_month') { year++; year_selector.value = year + '年'; selected_date_div.innerHTML = year_selector.value + month_selector.value; } return; } // var year = parseInt(year_selector.value); // var month = parseInt(month_selector.value); var month_offset = (year - year_range['low']) * 12 + month - 1; // [0, n_months - 1] if (this.id === 'go_prev_year') { month_offset -= 12; } else if (this.id === 'go_next_year') { month_offset += 12; } else if (this.id === 'go_prev_month') { month_offset -= 1; } else if (this.id === 'go_next_month') { month_offset += 1; } else { return; } if (month_offset < 0 || month_offset > n_months - 1) { return; } year_selector.value = Math.floor(month_offset / 12) + year_range['low'] + '年'; month_selector.value = month_offset % 12 === 0 ? 1 +'月': month_offset % 12 + 1 + '月'; selected_date_div.innerHTML = year_selector.value + month_selector.value; NeedUpdateYijiArea = false; create_page(parseInt(year_selector.value), parseInt(month_selector.value)); NeedUpdateYijiArea = true; }); } var holidays = ['元旦节', '春节', '清明节', '劳动节', '端午节', '中秋节', '国庆节']; var holiday_list = document.getElementById('holiday_list'); for (var index = 0; index < holidays.length; index++) { var li = document.createElement('LI'); li.innerHTML = holidays[index]; li.addEventListener('click', go_to_holiday); holiday_list.appendChild(li); } //var holiday_button = document.getElementById('holiday_button'); //holiday_button.addEventListener('click', popup_div); var today_button = document.getElementById('today_button'); today_button.addEventListener('click', function() { year_selector.value = today.getFullYear() + '年'; month_selector.value = today.getMonth() + 1 + '月'; selected_date_div.innerHTML = year_selector.value + month_selector.value; highlight_day = today.getDate(); convertToNormal(); year = today.getFullYear(); month = today.getMonth(); if(PrevClick != null) { PrevClick.style.border = "none"; PrevClick = null; } create_page(today.getFullYear(), today.getMonth() + 1); update_year_month_ui(); var header_id=document.getElementById("header"); var header_color=header_id.style.background; var x=document.getElementsByClassName("day_today"); var i; if (header_color == "rgb(0, 0, 0)"){ for (i = 0; i < x.length; i++) { x[i].style.backgroundColor = "#3593b5"; } } else{ for (i = 0; i < x.length; i++) { x[i].style.backgroundColor = header_color; } } }); calendar = document.getElementById('calendar_table'); create_page(parseInt(year_selector.value), parseInt(month_selector.value)); } function create_page(year, month) { if (year < year_range['low'] || year > year_range['high']) return; var month_stuff = LunarCalendar.calendar(year, month, true,1); highlight_day = highlight_day > month_stuff['monthDays'] ? month_stuff['monthDays'] : highlight_day; var current_row = null; var current_cell = null; for (var row = 1; row < 7; row++) { if (calendar.rows.length === row) { current_row = calendar.insertRow(row); } else { current_row = calendar.rows[row]; } for (var column = 0; column < 7; column++) { if (current_row.cells.length === column) { current_cell = current_row.insertCell(column); current_cell.addEventListener('click', function() { // if(this.children[0].innerHTML === "") // { // highlight_day = parseInt(this.children[1].innerHTML); // } // else // { highlight_day = parseInt(this.children[0].innerHTML); // } //highlight_day = parseInt(this.children[0].innerText); var cur_month = parseInt(month_selector.value); var cur_year = parseInt(year_selector.value); if(PrevClick != null) { PrevClick.style.border = "none"; } this.style.border = "1px solid #7eb4ea"; PrevClick = this; if (this.className === 'day_other_month' && highlight_day > 20) { // var cur_month = parseInt(month_selector.value); // var cur_year = parseInt(year_selector.value); if(1 == cur_month) { cur_month = 12; cur_year = cur_year - 1; } else { cur_month = cur_month - 1; } // create_page(cur_year, cur_month); update_right_pane(cur_year, cur_month, highlight_day); update_yiji_area_by_date(cur_year,cur_month); } else if(this.className === 'day_other_month' && highlight_day < 15) { // var cur_month = parseInt(month_selector.value); // var cur_year = parseInt(year_selector.value); if(12 == cur_month) { cur_month = 1; cur_year = cur_year + 1; } else { cur_month = cur_month + 1; } // create_page(cur_year, cur_month); update_right_pane(cur_year, cur_month, highlight_day); update_yiji_area_by_date(cur_year,cur_month); } else { create_page(parseInt(year_selector.value), parseInt(month_selector.value)); } }); } else { current_cell = current_row.cells[column]; } // var header_id=document.getElementById("header"); // var header_color=header_id.style.background; // if (header_color == "rgb(0, 0, 0)"){ // var x=document.getElementsByClassName("day_highlight"); // for (i = 0; i < x.length; i++) { // x[i].style.backgroundColor = "#151a1e"; // } // } // else{ // var x=document.getElementsByClassName("day_highlight"); // for (i = 0; i < x.length; i++) { // x[i].style.backgroundColor = "#ffffff"; // } // } // if((year == today.getFullYear()) && (month == today.getMonth())) // { // var x=document.getElementsByClassName("day_today"); // for (i = 0; i < x.length; i++) { // // x[i].style.backgroundColor = "#3593b5"; // x[i].style.backgroundColor = "#3d6be5"; // } // } // x=document.getElementsByClassName("day_today"); // for (i = 0; i < x.length; i++) { // // x[i].style.backgroundColor = "#3593b5"; // x[i].style.backgroundColor = "#3d6be5"; // } var index = (row - 1) * 7 + column; // [0, 7 * 6 - 1] /* * 注意判断顺序 * 1. 表格开头/结尾的非本月日期的单元格样式与其他单元格无关,需要最先判断 * 2. 其次是‘今天’的单元格样式 * 3. 再次是当前鼠标点击选中的单元格 * 4. 再次是属于周末的单元格 * 5. 最后是其他普通单元格 */ if ((index < (month_stuff['firstDay'] -1) && month_stuff['firstDay'] != 0)//每周从周一开始,当月第一天不是星期天,上个月的日期 ||(index < 6 && month_stuff['firstDay'] === 0)//第一天是星期天 || (month_stuff['firstDay']===0 && index >= (month_stuff['monthDays'] + 6))//第一天是星期天下月的日期 ||( month_stuff['firstDay'] != 0 && index >= month_stuff['firstDay'] + month_stuff['monthDays']-1)) //第一天不是星期天下月日期 { current_cell.className = 'day_other_month'; } else if (today.getDate() === month_stuff['monthData'][index]['day'] && today.getMonth() === month - 1 && today.getFullYear() === year) { current_cell.className = 'day_today'; } else if (((month_stuff['firstDay'] != 0)&&(index === highlight_day + month_stuff['firstDay'] - 1 -1)) ||((month_stuff['firstDay'] === 0)&&(index === highlight_day + 5)) ) { current_cell.className = 'day_highlight'; } else if (column === 5 || column === 6) { current_cell.className = 'day_weekend'; } else { current_cell.className = 'day_this_month'; } var lunar_day; if ((month_stuff['monthData'][index]['lunarFestival'])&&(month_stuff['monthData'][index]['solarFestival'])){ lunar_day = month_stuff['monthData'][index]['solarFestival']; }else if (month_stuff['monthData'][index]['solarFestival']) { lunar_day = month_stuff['monthData'][index]['solarFestival']; }else if(month_stuff['monthData'][index]['lunarFestival']){ lunar_day = month_stuff['monthData'][index]['lunarFestival']; }else if(month_stuff['monthData'][index]['term']){ lunar_day = month_stuff['monthData'][index]['term']; }else { lunar_day = month_stuff['monthData'][index]['lunarDayName']; } // if (month_stuff['monthData'][index]['lunarFestival']) { // lunar_day = month_stuff['monthData'][index]['lunarFestival']; // // } else if (month_stuff['monthData'][index]['solarFestival']) { // // lunar_day = month_stuff['monthData'][index]['solarFestival']; // } else { // lunar_day = month_stuff['monthData'][index]['lunarDayName']; // } var worktime = null; if (month_stuff['monthData'][index]['worktime'] === 2) { worktime = document.createElement("SPAN"); worktime.className = 'worktime2'; worktime.innerHTML = '休'; } else if (month_stuff['monthData'][index]['worktime'] === 1) { worktime = document.createElement("SPAN"); worktime.className = 'worktime1'; worktime.innerHTML = '班'; } else { } current_cell.innerHTML = '' + month_stuff['monthData'][index]['day'] + '' + '
' + '' + lunar_day + ''; // if (worktime && current_cell.className !== 'day_other_month') { // current_cell.appendChild(worktime); // } if (worktime) { current_cell.appendChild(worktime); } // if (month_stuff['monthData'][index]['worktime'] === 2) { // worktime = document.createElement("SPAN"); // worktime.className = 'worktime2'; // worktime.innerHTML = ' '; // } else if (month_stuff['monthData'][index]['worktime'] === 1) { // worktime = document.createElement("SPAN"); // worktime.className = 'worktime1'; // worktime.innerHTML = ' '; // } else { // } // /*myworktime.innerHTML = '' + // month_stuff['monthData'][index]['day'] + // '' + // '
' + // '' + // lunar_day + // '';*/ // if (worktime && current_cell.className !== 'day_other_month') { // //current_cell.appendChild(worktime); // //
// // document.getElementById('aa').innerHTML = worktime.innerHTML; // current_cell.innerHTML = worktime.innerHTML+ // // '
'+ // ' ' + // month_stuff['monthData'][index]['day'] + // '' + // '
' + // '' + // lunar_day + // ''; // // current_cell.innerHTML = '123' // // +'
' + '456'+ // // '
' +'789'; // } // else // { // current_cell.innerHTML = '' + // month_stuff['monthData'][index]['day'] + // '' + // '
' + // '' + // lunar_day + // ''; // } } } update_right_pane(year, month, highlight_day); month_stuff = null; if (header_color == "rgb(0, 0, 0)"){ var day_this_month_len=document.getElementsByClassName('day_this_month').length; for (var i=0; i",""); year_selector.value = str.replace("",""); document.getElementById('year_div').className = 'hidden_div'; calendar.style.display = ""; } else if (this.parentNode.className=== 'show_months') { var str = this.innerHTML.replace("",""); month_selector.value = str.replace("",""); document.getElementById('month_div').className = 'hidden_div'; calendar.style.display = ""; } selected_date_div.innerHTML = year_selector.value + month_selector.value; create_page(parseInt(year_selector.value), parseInt(month_selector.value)); } function popup_div(event) { var x = event.clientX - event.offsetX; var y = event.clientY - event.offsetY; var div; // TODO var width = 64; var height = 20; if (this.id === 'year_button') { div = document.getElementById('year_div'); div_range.year.x_min = x; div_range.year.x_max = x + width; div_range.year.y_min = y; div_range.year.y_max = y + height; if (div.className === 'hidden_div') { div.className = 'visible_div'; document.getElementById('month_div').className = 'hidden_div'; calendar.style.display = "none"; year = parseInt(year_selector.value); var li = document.getElementById('year_div'); year_selector.value = year + '年'; // selected_date_div.innerHTML = year_selector.value + month_selector.value; for (var index = 0; index < 16; index++) { // li.children[0].children[index].innerHTML = '
'; var currentYear = year + index; //li.children[0].children[index].innerHTML= '
' + curretYear + '年'; li.children[0].children[index].innerHTML =''+ currentYear+ '年' + ''; li.children[0].children[index].addEventListener('click', new_month_selected); // new year implies new month } } else { div.className = 'hidden_div'; calendar.style.display = ""; } } else if (this.id === 'month_button') { div = document.getElementById('month_div'); div_range.month.x_min = x; div_range.month.x_max = x + width; div_range.month.y_min = y; div_range.month.y_max = y + height; if (div.className === 'hidden_div') { div.className = 'visible_div'; document.getElementById('year_div').className = 'hidden_div'; calendar.style.display = "none"; } else { div.className = 'hidden_div'; calendar.style.display = ""; } } else { return; } // if (div.className === 'hidden_div') { // div.className = 'visible_div'; // calendar.style.display = "none"; // } else { // div.className = 'hidden_div'; // calendar.style.display = ""; // } div.style.left = x + 'px'; div.style.top = y + height + 'px'; update_year_month_ui(); //updateUi(); } function update_right_pane(year, month, day) { var month_stuff = LunarCalendar.calendar(year, month, true, 1); var general_datetime_list = document.getElementById('general_datetime_list'); var datetime_container = document.getElementById('datetime_container'); // var highlight_index = month_stuff['firstDay'] + day - 1; var highlight_index = null; if(month_stuff['firstDay'] === 0)//index of this data is six { highlight_index = day -1 + 6; } else { highlight_index = month_stuff['firstDay'] -1 + day - 1;//firstDay's index is firstDay - 1 } var lunar_month_name = month_stuff['monthData'][highlight_index]['lunarMonthName']; var lunar_day_name = month_stuff['monthData'][highlight_index]['lunarDayName']; var ganzhi_year = month_stuff['monthData'][highlight_index]['GanZhiYear']; var ganzhi_month = month_stuff['monthData'][highlight_index]['GanZhiMonth']; var ganzhi_day = month_stuff['monthData'][highlight_index]['GanZhiDay']; var zodiac = month_stuff['monthData'][highlight_index]['zodiac']; var weekday = weekdays[(highlight_index + 1) % 7]; var month_str = month.toString(); if (month <= 9) { month_str = '0' + month; } var day_str = day.toString(); if (day <= 9) { day_str = '0' + day; } if(NeedChangeCurrentTime) { datetime_container.children[1].innerHTML = year + '-' + month_str + '-' + day_str + ' 星期' + weekday + ' '+lunar_month_name + lunar_day_name; NeedChangeCurrentTime = 0; } /* general_datetime_list.children[0].innerHTML = year + '-' + month_str + '-' + day_str + ' 星期' + weekday; general_datetime_list.children[1].innerHTML = day_str; // e.g. 06 general_datetime_list.children[2].innerHTML = lunar_month_name + lunar_day_name;*/ //general_datetime_list.children[0].innerHTML = ganzhi_year + '年' + '【' + zodiac + '年' + '】' + ganzhi_month + '月 ' + ganzhi_day + '日'; // general_datetime_list.children[1].innerHTML = ganzhi_month + '月 ' + ganzhi_day + '日'; updateTime(); if(NeedUpdateYijiArea) { general_datetime_list.children[0].innerHTML = lunar_month_name + lunar_day_name +'    '+ganzhi_year + '年' + '【' + zodiac + '年' + '】' + ganzhi_month + '月 ' + ganzhi_day + '日'; update_yiji_area(); } NeedUpdateYijiArea = true; month_stuff = null; } /* 节日查找从当月开始往后查找,包括公历节日、农历节日和农历节气,最多只查找到下一年 */ function go_to_holiday () { var year = today.getFullYear(); var month = today.getMonth() + 1; var day = 0; var month_stuff = LunarCalendar.calendar(year, month, false, 1); var found = false; var target = this.innerHTML; do { for (var index = 0; index < month_stuff['monthDays']; index++) { if (target.indexOf(month_stuff['monthData'][index]['solarFestival']) >= 0 || target.indexOf(month_stuff['monthData'][index]['lunarFestival']) >= 0 || target.indexOf(month_stuff['monthData'][index]['term']) >= 0) { day = index + 1; found = true; break; } } if (found) { break; } if (month === 12) { year++; month = 1; } else { month++; } month_stuff = LunarCalendar.calendar(year, month, false, 1); } while (year - today.getFullYear() <= 1); if (!found) { return; } year_selector.value = year + '年'; month_selector.value = month + '月'; highlight_day = day; create_page(year, month); month_stuff = null; } ukui-panel-3.0.6.4/plugin-calendar/html/ukui-en.html0000644000175000017500000000426014204636772020645 0ustar fengfeng
Sun Mon Thes Wed Thur Fri Sat
  1. 2015-02-04 星期三
  2. 4
  3. 十一月十四
  4. 甲午年【马年】
  5. 丙子月 庚辰日
ukui-panel-3.0.6.4/plugin-calendar/html/jiejiari.js0000644000175000017500000000746714203402514020522 0ustar fengfeng{ "worktime.y2013":{"d0101":"2","d0102":"2","d0103":"2","d0105":"1","d0106":"1","d0209":"2","d0210":"2","d0211":"2","d0212":"2","d0213":"2","d0214":"2","d0215":"2","d0216":"1","d0217":"1","d0404":"2","d0405":"2","d0406":"2","d0407":"1","d0427":"1","d0428":"1","d0429":"2","d0430":"2","d0501":"2","d0608":"1","d0609":"1","d0610":"2","d0611":"2","d0612":"2","d0919":"2","d0920":"2","d0921":"2","d0922":"1","d0929":"1","d1001":"2","d1002":"2","d1003":"2","d1004":"2","d1005":"2","d1006":"2","d1007":"2","d1012":"1"}, "worktime.y2014":{"d0101":"2","d0126":"1","d0131":"2","d0201":"2","d0202":"2","d0203":"2","d0204":"2","d0205":"2","d0206":"2","d0208":"1","d0405":"2","d0407":"2","d0501":"2","d0502":"2","d0503":"2","d0504":"1","d0602":"2","d0908":"2","d0928":"1","d1001":"2","d1002":"2","d1003":"2","d1004":"2","d1005":"2","d1006":"2","d1007":"2","d1011":"1"}, "worktime.y2015":{"d0101":"2","d0102":"2","d0103":"2","d0104":"1","d0215":"1","d0218":"2","d0219":"2","d0220":"2","d0221":"2","d0222":"2","d0223":"2","d0224":"2","d0228":"1","d0404":"2","d0405":"2","d0406":"2","d0501":"2","d0502":"2","d0503":"2","d0620":"2","d0621":"2","d0622":"2","d0926":"2","d0927":"2","d1001":"2","d1002":"2","d1003":"2","d1004":"2","d1005":"2","d1006":"2","d1007":"2","d1010":"1"}, "worktime.y2018":{"d0101":"2","d0211":"1","d0215":"2","d0216":"2","d0217":"2","d0218":"2","d0219":"2","d0220":"2","d0221":"2","d0224":"1","d0405":"2","d0406":"2","d0407":"2","d0408":"1","d0428":"1","d0429":"2","d0430":"2","d0501":"2","d0616":"2","d0617":"2","d0618":"2","d0922":"2","d0923":"2","d0924":"2","d0929":"1","d0930":"1","d1001":"2","d1002":"2","d1003":"2","d1004":"2","d1005":"2","d1006":"2","d1007":"2","d1229":"1","d1230":"2","d1231":"2"}, "worktime.y2019":{"d0101":"2","d0202":"1","d0203":"1","d0204":"2","d0205":"2","d0206":"2","d0207":"2","d0208":"2","d0209":"2","d0210":"2","d0405":"2","d0406":"2","d0407":"2","d0501":"2","d0502":"2","d0503":"2","d0504":"2","d0505":"1","d0607":"2","d0608":"2","d0609":"2","d0913":"2","d0914":"2","d0915":"2","d0929":"1","d1001":"2","d1002":"2","d1003":"2","d1004":"2","d1005":"2","d1006":"2","d1007":"2","d1012":"1"}, "worktime.y2020":{"d0101":"2","d0119":"1","d0124":"2","d0125":"2","d0126":"2","d0127":"2","d0128":"2","d0129":"2","d0130":"2","d0201":"1","d0404":"2","d0405":"2","d0406":"2","d0426":"1","d0501":"2","d0502":"2","d0503":"2","d0504":"2","d0505":"2","d0509":"1","d0625":"2","d0626":"2","d0627":"2","d0628":"1","d0927":"1","d1001":"2","d1002":"2","d1003":"2","d1004":"2","d1005":"2","d1006":"2","d1007":"2","d1008":"2","d1010":"1"}, "worktime.y2021":{ "d0101":"2","d0102":"2","d0103":"2", "d0207":"1","d0211":"2","d0212":"2","d0213":"2","d0214":"2","d0215":"2","d0216":"2","d0217":"2","d0220":"1", "d0403":"2","d0404":"2","d0405":"2","d0425":"1", "d0501":"2","d0502":"2","d0503":"2","d0504":"2","d0505":"2","d0508":"1", "d0612":"2","d0613":"2","d0614":"2", "d0918":"1","d0919":"2","d0920":"2","d0921":"2","d0926":"1", "d1001":"2","d1002":"2","d1003":"2","d1004":"2","d1005":"2","d1006":"2","d1007":"2","d1009":"1" }, "worktime.y2022":{ "d0101":"2","d0102":"2","d0103":"2","d0129":"1","d0130":"1","d0131":"2", "d0201":"2","d0202":"2","d0203":"2","d0204":"2","d0205":"2","d0206":"2", "d0402":"1","d0403":"2","d0404":"2","d0405":"2","d0424":"1","d0430":"2", "d0501":"2","d0502":"2","d0503":"2","d0504":"2","d0507":"1", "d0603":"2","d0604":"2","d0605":"2", "d0910":"2","d0911":"2","d0912":"2", "d1001":"2","d1002":"2","d1003":"2","d1004":"2","d1005":"2","d1006":"2","d1007":"2","d1008":"1","d1009":"1" }, "worktime.y2023":{ "d0101":"2","d0102":"2","d0103":"2" } } ukui-panel-3.0.6.4/plugin-calendar/html/arm64.css0000644000175000017500000001210514204636772020042 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see

12:42:53

2020年1月1日

2020年3月
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
ukui-panel-3.0.6.4/plugin-calendar/html/index-fr.js0000644000175000017500000004136214204636772020460 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see div_range.year.x_max || x < div_range.year.x_min || y > div_range.year.y_max || y < div_range.year.y_min) { year_div.className = 'hidden_div'; } } if (month_div.className === 'visible_div') { if (x > div_range.month.x_max || x < div_range.month.x_min || y > div_range.month.y_max || y < div_range.month.y_min ) { month_div.className = 'hidden_div'; } } /* if (holiday_div.className === 'visible_div') { if (x > div_range.holiday.x_max || x < div_range.holiday.x_min || y > div_range.holiday.y_max || y < div_range.holiday.y_min ) { holiday_div.className = 'hidden_div'; } }*/ }); for (var index = year_range['low']; index <= year_range['high']; index++) { var li = document.createElement('LI'); li.innerHTML = index; li.addEventListener('click', new_month_selected); // new year implies new month year_list.appendChild(li); if (index === year) { year_selector.value = index; } } for (var index = 1; index <= 12; index++) { var li = document.createElement('LI'); li.innerHTML = index; li.addEventListener('click', new_month_selected); month_list.appendChild(li); if (index === month + 1) { month_selector.value = index; } } var goto_arrows = document.getElementsByTagName('input'); var n_months = (year_range['high'] - year_range['low'] + 1) * 12; for (var index = 0; index < goto_arrows.length; index++) { goto_arrows[index].addEventListener('click', function() { var year = parseInt(year_selector.value); var month = parseInt(month_selector.value); var month_offset = (year - year_range['low']) * 12 + month - 1; // [0, n_months - 1] if (this.id === 'go_prev_year') { month_offset -= 12; } else if (this.id === 'go_next_year') { month_offset += 12; } else if (this.id === 'go_prev_month') { month_offset -= 1; } else if (this.id === 'go_next_month') { month_offset += 1; } else { return; } if (month_offset < 0 || month_offset > n_months - 1) { return; } year_selector.value = Math.floor(month_offset / 12) + year_range['low']; month_selector.value = month_offset % 12 === 0 ? 1 : month_offset % 12 + 1; create_page(parseInt(year_selector.value), parseInt(month_selector.value)); }); } /* var holidays = ['元旦节', '春节', '清明节', '劳动节', '端午节', '中秋节', '国庆节']; var holiday_list = document.getElementById('holiday_list'); for (var index = 0; index < holidays.length; index++) { var li = document.createElement('LI'); li.innerHTML = holidays[index]; li.addEventListener('click', go_to_holiday); holiday_list.appendChild(li); }*/ // var holiday_button = document.getElementById('holiday_button'); // holiday_button.addEventListener('click', popup_div); var today_button = document.getElementById('today_button'); today_button.addEventListener('click', function() { year_selector.value = today.getFullYear(); month_selector.value = today.getMonth() + 1; highlight_day = today.getDate(); create_page(today.getFullYear(), today.getMonth() + 1); }); calendar = document.getElementById('calendar_table'); create_page(parseInt(year_selector.value), parseInt(month_selector.value)); } function create_page(year, month) { if (year < year_range['low'] || year > year_range['high']) return; var month_stuff = LunarCalendar.calendar(year, month, true); highlight_day = highlight_day > month_stuff['monthDays'] ? month_stuff['monthDays'] : highlight_day; var current_row = null; var current_cell = null; for (var row = 1; row < 7; row++) { if (calendar.rows.length === row) { current_row = calendar.insertRow(row); } else { current_row = calendar.rows[row]; } for (var column = 0; column < 7; column++) { if (current_row.cells.length === column) { current_cell = current_row.insertCell(column); current_cell.addEventListener('click', function() { highlight_day = parseInt(this.children[0].innerHTML); if (this.className === 'day_other_month') { return; } create_page(parseInt(year_selector.value), parseInt(month_selector.value)); }); } else { current_cell = current_row.cells[column]; } var index = (row - 1) * 7 + column; // [0, 7 * 6 - 1] /* * 注意判断顺序 * 1. 表格开头/结尾的非本月日期的单元格样式与其他单元格无关,需要最先判断 * 2. 其次是‘今天’的单元格样式 * 3. 再次是当前鼠标点击选中的单元格 * 4. 再次是属于周末的单元格 * 5. 最后是其他普通单元格 */ if (index < month_stuff['firstDay'] || index >= month_stuff['firstDay'] + month_stuff['monthDays']) { current_cell.className = 'day_other_month'; } else if (today.getDate() === month_stuff['monthData'][index]['day'] && today.getMonth() === month - 1 && today.getFullYear() === year) { current_cell.className = 'day_today'; } else if (index === highlight_day + month_stuff['firstDay'] - 1) { current_cell.className = 'day_highlight'; } else if (column === 0 || column === 6) { current_cell.className = 'day_weekend'; } else { current_cell.className = 'day_this_month'; } var lunar_day; if (month_stuff['monthData'][index]['lunarFestival']) { lunar_day = month_stuff['monthData'][index]['lunarFestival']; // } else if (month_stuff['monthData'][index]['solarFestival']) { // lunar_day = month_stuff['monthData'][index]['solarFestival']; } else { lunar_day = month_stuff['monthData'][index]['lunarDayName']; } var worktime = null; if (month_stuff['monthData'][index]['worktime'] === 2) { // worktime = document.createElement("SPAN"); worktime.className = 'worktime2'; // worktime.innerHTML = '休'; } else if (month_stuff['monthData'][index]['worktime'] === 1) { // worktime = document.createElement("SPAN"); worktime.className = 'worktime1'; // worktime.innerHTML = '班'; } else { } current_cell.innerHTML = '' + month_stuff['monthData'][index]['day'] + '' + '
' + '' + ''; if (worktime && current_cell.className !== 'day_other_month') { // current_cell.appendChild(worktime); } } } update_right_pane(year, month, highlight_day); month_stuff = null; } function new_month_selected() { if (this.parentNode.id === 'year_list') { year_selector.value = this.innerHTML; document.getElementById('year_div').className = 'hidden_div'; } else if (this.parentNode.id === 'month_list') { month_selector.value = this.innerHTML; document.getElementById('month_div').className = 'hidden_div'; } create_page(parseInt(year_selector.value), parseInt(month_selector.value)); } function popup_div(event) { var x = event.clientX - event.offsetX; var y = event.clientY - event.offsetY; var div; // TODO var width = 64; var height = 20; if (this.id === 'year_selector') { div = document.getElementById('year_div'); div_range.year.x_min = x; div_range.year.x_max = x + width; div_range.year.y_min = y; div_range.year.y_max = y + height; } else if (this.id === 'month_selector') { div = document.getElementById('month_div'); div_range.month.x_min = x; div_range.month.x_max = x + width; div_range.month.y_min = y; div_range.month.y_max = y + height; } /* else if (this.id === 'holiday_button') { div = document.getElementById('holiday_div'); div.style.width = '64px'; div.style.height = '100px'; div_range.holiday.x_min = x; div_range.holiday.x_max = x + width; div_range.holiday.y_min = y; div_range.holiday.y_max = y + height; }*/else { return; } if (div.className === 'hidden_div') { div.className = 'visible_div'; } else { div.className = 'hidden_div'; } div.style.left = x + 'px'; div.style.top = y + height + 'px'; } function update_right_pane(year, month, day) { var month_stuff = LunarCalendar.calendar(year, month, true); var general_datetime_list = document.getElementById('general_datetime_list'); var highlight_index = month_stuff['firstDay'] + day - 1; var lunar_month_name = month_stuff['monthData'][highlight_index]['lunarMonthName']; var lunar_day_name = month_stuff['monthData'][highlight_index]['lunarDayName']; var ganzhi_year = month_stuff['monthData'][highlight_index]['GanZhiYear']; var ganzhi_month = month_stuff['monthData'][highlight_index]['GanZhiMonth']; var ganzhi_day = month_stuff['monthData'][highlight_index]['GanZhiDay']; var zodiac = month_stuff['monthData'][highlight_index]['zodiac']; var weekday = weekdays[highlight_index % 7]; var month_str = month.toString(); if (month <= 9) { month_str = '0' + month; } var day_str = day.toString(); if (day <= 9) { day_str = '0' + day; } general_datetime_list.children[0].innerHTML = month_str + '-' + day_str + '-' + year + ' ' + weekday; general_datetime_list.children[1].innerHTML = day_str; // e.g. 06 general_datetime_list.children[2].innerHTML = ' '; general_datetime_list.children[3].innerHTML = ' '; general_datetime_list.children[4].innerHTML = ' '; //update_yiji_area(); month_stuff = null; } /* 节日查找从当月开始往后查找,包括公历节日、农历节日和农历节气,最多只查找到下一年 */ /*function go_to_holiday () { var year = today.getFullYear(); var month = today.getMonth() + 1; var day = 0; var month_stuff = LunarCalendar.calendar(year, month, false); var found = false; var target = this.innerHTML; do { for (var index = 0; index < month_stuff['monthDays']; index++) { if (target.indexOf(month_stuff['monthData'][index]['solarFestival']) >= 0 || target.indexOf(month_stuff['monthData'][index]['lunarFestival']) >= 0 || target.indexOf(month_stuff['monthData'][index]['term']) >= 0) { day = index + 1; found = true; break; } } if (found) { break; } if (month === 12) { year++; month = 1; } else { month++; } month_stuff = LunarCalendar.calendar(year, month, false); } while (year - today.getFullYear() <= 1); if (!found) { return; } year_selector.value = year; month_selector.value = month + 'Month'; highlight_day = day; create_page(year, month); month_stuff = null; }*/ ukui-panel-3.0.6.4/plugin-calendar/html/ukui.css0000644000175000017500000002545014204636772020075 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see

12:42:53

2020年1月1日

2020年3月
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
ukui-panel-3.0.6.4/plugin-calendar/html/ukui-ru.html0000644000175000017500000000562314204636772020675 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see
ВС ПН ВТ СР ЧТ ПТ СБ
  1. 2015-02-04 星期三
  2. 4
  3. 十一月十四
  4. 甲午年【马年】
  5. 丙子月 庚辰日
ukui-panel-3.0.6.4/plugin-calendar/html/ukui-min.css0000644000175000017500000002526114204636772020656 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see

12:42:53

2020-01-01

2020.3
Mon Tue Wed Thur Fri Sat Sun
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
ukui-panel-3.0.6.4/plugin-calendar/html/arm64.html0000644000175000017500000000563214204636772020225 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see
  1. 2015-02-04 星期三
  2. 4
  3. 十一月十四
  4. 甲午年【马年】
  5. 丙子月 庚辰日
迁徙 嫁娶
祭祀 安葬
开光 破土
祈福 作梁
ukui-panel-3.0.6.4/plugin-calendar/html/images/0000755000175000017500000000000014204636772017645 5ustar fengfengukui-panel-3.0.6.4/plugin-calendar/html/images/next.png0000644000175000017500000000230214204636772021326 0ustar fengfengPNG  IHDR00WtEXtSoftwareAdobe ImageReadyqe<&iTXtXML:com.adobe.xmp !x2IDATx 0qNAEWp wv GW'P PB{/5Mlqͫi~09\9ЌlӜ3=; pY3!fO4+OOH!ba_" 1Px&n3kS|['(o{H"d'1'%U_.Tw!{m4E<,"(bjL6!4xniKhПU2^֐%/ g`` TIENDB`ukui-panel-3.0.6.4/plugin-calendar/html/images/prev.png0000644000175000017500000000216614204636772021334 0ustar fengfengPNG  IHDR00WtEXtSoftwareAdobe ImageReadyqe<&iTXtXML:com.adobe.xmp eIDATxM 0+ WIDATxb?@&uXr̲CSNX1 ld-īx7+%@l=d8d (I:fg೜4@#-KlH#H\@dYNj6-'@w8%[!;b%SR˱$:"dmB Q:`#2[qIENDB`ukui-panel-3.0.6.4/plugin-calendar/html/images/up.png0000644000175000017500000000203414204636772020776 0ustar fengfengPNG  IHDR szztEXtSoftwareAdobe ImageReadyqe<&iTXtXML:com.adobe.xmp XT[IDATx; 0xc$x=Tl6 E !HSICkC#@mQ|LqC+jВ^CEMhGۀu\&DdD$Er\xc\p)%( 8hq IENDB`ukui-panel-3.0.6.4/plugin-calendar/html/images/up_click.png0000644000175000017500000000206614204636772022150 0ustar fengfengPNG  IHDR szztEXtSoftwareAdobe ImageReadyqe<&iTXtXML:com.adobe.xmp $ IDATxb?@&uF.pf[`M`2 jhy(*ur nb $,dZ |T\Giy rh -g,T"GPrBrh>'rBeIv#zE1hxuw@ˋ4>IENDB`ukui-panel-3.0.6.4/plugin-calendar/html/images/header-bg.png0000644000175000017500000000204314204636772022170 0ustar fengfengPNG  IHDR & tEXtSoftwareAdobe ImageReadyqe<qiTXtXML:com.adobe.xmp ROMHIDATxb1!?aE dt6ETs tn&1(0h*0@pfQIENDB`ukui-panel-3.0.6.4/plugin-calendar/html/images/down_click.png0000644000175000017500000000211614204636772022467 0ustar fengfengPNG  IHDR szztEXtSoftwareAdobe ImageReadyqe<&iTXtXML:com.adobe.xmp 6 IDATxb?@&uX̲} NX1 ld-īx7+%@l=d8d (I:fg೜4@#-KlH#H\@dYNj6-'@w8%[!;b%SR˱$:"dmB Q:`#2[OcIENDB`ukui-panel-3.0.6.4/plugin-calendar/html/images/shangban.png0000644000175000017500000000312214204636772022132 0ustar fengfengPNG  IHDR$$tEXtSoftwareAdobe ImageReadyqe<&iTXtXML:com.adobe.xmp Δ[IDATxb|@T] $ԁ 0 @;h@ ژ4X|qjV1DSdgg@9,l/V>3|9U N3<:UQ-U@;مlA2|8\{Iw$!lnx/2|PAy~7_ODϯgG~EHq dPZNebd"1AAT!!2EB.lG??AEHebD C8UE j%AexspafLy}%@ltO0q301D^uG lX&fxP6#>vk$RUF}> $M"j#* }5 |64-&xqE'!&< 6w2T_m'^P@ ^VY pq4:<>L!AVpyu,*XQ`w}P"/{Zix Fx=Ar.Ϣ8!Sz O=_E9? ǀP r PAn`I/IENDB`ukui-panel-3.0.6.4/plugin-calendar/html/images/up_hover.png0000644000175000017500000000206614204636772022206 0ustar fengfengPNG  IHDR szztEXtSoftwareAdobe ImageReadyqe<&iTXtXML:com.adobe.xmp IDATxb?@&uF.`f"E`2 jhy(*ur nb $,dZ |T\Giy rh -g,T"GPrBrh>'rBeIv#zE1hxuw@4pIENDB`ukui-panel-3.0.6.4/plugin-calendar/html/images/selected.png0000644000175000017500000000223314204636772022143 0ustar fengfengPNG  IHDR szztEXtSoftwareAdobe ImageReadyqe<&iTXtXML:com.adobe.xmp @ IDATx얿 0[:T TD)}ZG.t?CW$iR R.K/eYZ]F8c  GDc?3{P5wpjTl\TG:^lק ~Wǐ{ nӀOBYקmI(!.3HI(|{XiT& >IDATx!0J *O1AEˋYHQUǾ50ٓnNvf]% H@1`-9O>Nq`I?: zSc=՟3"a ȕ0[RTU &A3#DNLa/ %>$P[``'3IENDB`ukui-panel-3.0.6.4/plugin-calendar/html/images/xiuxi.png0000644000175000017500000000275114204636772021526 0ustar fengfengPNG  IHDR szztEXtSoftwareAdobe ImageReadyqe<&iTXtXML:com.adobe.xmp D7YIDATxW;H`$?$HAt\S⠅N.N""N:  "T8v$: (RQԻ?4iM҃Kir}w]"|on<): J zZE!QSI'1:y"Zi05r9 0Tc0żZJ &j|Z87(yPk@Qr9t66Уw ,.JїJzn6aXt} wg{ 33 H .-F?l$ݞsj0Noo`K +p#)Ẇe&rJ*5;_Y%[Ƶ5)۞jɂ0 R?; lu{}ՊF,flf |H<-w..xyȖ/0`[+ޜ~yiޗp "ˠ!Y°cZ =L\^-g+ab/?:8N $ <9%D0r$h Z#h}(J=Jk=/ 0i:=`XIENDB`ukui-panel-3.0.6.4/plugin-calendar/html/images/select.png0000644000175000017500000000213314204636772021631 0ustar fengfengPNG  IHDR szztEXtSoftwareAdobe ImageReadyqe<&iTXtXML:com.adobe.xmp .IDATx앱 0@[vũ~`⪣_܄$$P(wr$w1&2Iǡ*CǼ1저̒[CgxNp;|,9aGx Wa 7P}0shhkF U@z!Px!Plo% N)Q%J$K$vjg2qҴiӬM6iIL2L=63M,I$8VlYB2]$A @\@b!9Q @$3w<>{s//DBaH"4ME 8%yNS\`h:V `fid|e((I>O *, 4E/;EǮ6y׾=]p$IREIQՁs2 l H~Y@ߧgB]0n>.q}gIxve%a Lhκ^e$1!Hͺ󸋞s mp -+x:X<-w;g fj4bɩdKzHT c奞=i1Bۺh =C^;79 Ɔ/lOsm$}UUկ\J/SŁf1Jw /Iu8P,Tb89 ;vwQa#= C?(z!+7)#-S37t(y|hΝ>AF} /޸,4=B1xsA@/Dc?xf>YB9>.k$){U](pvk;X,f"l|n<mV^j66ԟ(88Lgzmૢ(~ⵛL1qꆉw Qr;&A_7!B̆mj<Օ,p@u`/ݸ].0LA._gtḋ]PqC~`G)rݢ( &oI9~[m5K`ϷAmM5\h'+JĈCF7=.]=#,v#^#^0L|:-*t+7a9!߭ Ȳ2ac$} ~W@NFK<~\i顣7 lbqsTW^9 ݏ9{l_BBݠJUv^v7fB1!rIpm ^h.<Ů[ BQUUمK׬SlT[EEQxlUepot DIjT5x_we1lVra쾹AUU[6UU?M(}`,/య}mDZ=Y^}oFyW.QJܤDut]HcY.w "d}y.gx{{\: ߒeej_ Ћ^' gOUeщHDacҪ}q=2bxtkBYh]PUw«DaiN{CA!kA(W3y+ aGjd,7f\` :Cs chG~>~#WO@ 0 yyL<[64eJS17'o($y|Zne@GGNЙ2`|Pwx9Ai#8KTBH'79]uLgE8F#CoЎbz&$ cmAH_0lffC1745[K)4c$G;m'@`RjGv󋋜(JGmEbOUCHIC[WPo/NQ_WC8tRRHilF10S +2^(,9}-yͶݸSA&}UT F8Pm~k1-$qv`~g|bry8Xe[U&<:NfUs˧M]? z`9@lĘ/k #Z2 Bx|F g"wIgͦiUUW^\Uar:Ut͖Dqf+2X Ul^o¿ᘬUvt@t L꤅q sCꊩ_yռc BP?N8lM[kLeh4(tL%`$3^Gy[{Zn`PUD\ؠbYz Fch4}{wecΏF9|q$=j%*-UoZ;ֺ2 w_;ی rIl aa=Qo&X'W TuXymdG>:}HYhi9E.LϕH{cEhszf׷#KNIǘ&SI<$5Z3 ZwZ,gk xeޒo50K:F: o޹8cuџF w$vS(eɧ1OO?`( .Ƈi7;mCQw_AO4E3iג 9Ң'/XT,- %fCs/ F]=0=3K 1~8XTd&g;}ʲt@bUUt$sʲ/w?6IQTaďgCOuto P=LztS.,T8\y i(R2c3՘Ϥ S'gLlk]w bt6h̦ iőC~[9\mn,$'#EŠP˒$_@pvnw;R6떶vxJKu9X7S =P(GelQuǦg\-ttYS9wI.]@lmmۂ ~x?,$a?2QMks]HhCr$af/XbV0M)//Z]=EQǎhOT%t"!L(X[GOكO?qP90l;\r*d78z2 GWHJ'DQHlS\vi+O;ϔzYijL۹ ;~\QӉz'&T;Z8P/,_BH/=mOȭ|dqQaQ0]QYV8vMK謸z7z`_gJRZo](z'&:l89 fYCH0gr$T*޼*$6ŜKh Fu|&VŞ`6jq~ԧ>8HfՒ.% ا/,..C1.7J{*dEQ^i3,{&D=Wouqb Жm:ʵZd+ÞbYXlX N_74ee'e]NU D"qo=,2[MuųrDyWF qj86O^e.24n(ꪏb,棂Ō ц ,˰os)6 oa"paIENDB`ukui-panel-3.0.6.4/plugin-calendar/html/images/zodiac/black/black-pig.png0000644000175000017500000001675514204636772024547 0ustar fengfengPNG  IHDRiV̮BIDATxyxg?۲|GIΝ4Z: X,>ߵFKu4jH" z׮w2&ϵ|v0oj^R@H|u׸Be/\B~Jlx}fUݾnp!3{'&o9ةs mA$qeF'+娩*ҫD"!-i%mgOJQQV :vO=#oֹ%=OLux]6@ 4՛ ٺX,Ҷ3WZpmVӠzN@fwK8>3:6؄ʓb^:2NR*{jlϝ8s_m߸ܞW3.>f!OC$m2~9lB(w _rU6WG"Ʌt4O$5.5Ӱ}xG=}W;\AQo޼RoD8cKfT((h#HbS 3Y&ST B0c~gf?]n k=d>9-\$ SӜ8s! k7VQV\@ +80LҢ/\iaGdJ"Vtʃv;^HGQ;΅csH)+MF=;2߿kY&C# LÑ^;Px$w udgr{^^O>vUdJ@ DIc.gv/Ik>9r3s?E"霾FZ-Pe*ߜ҇--?O$! }*d2idsjڳn{2}X6k 4$ k8% DB vMpx ,#G8zh4ѨU@ 8Mb1JWG݂hQTwt $ d2)j,c;g*enyILQ"6]n˥۬z+ܝP ?i&&'YrD赚:f^%ln=I}f ;{bqݾܯh5tx RT0,~yǽ!D"{x[_A{43_zV))+.Ia] [~MjLFE4Orhtn2d)ZHͣiDSZVsV^$RROEY Y@v ZP(\x(oi?t: t5n,"126Nvx<؄F B^g9!3=54m9 IR*;UJEbѝfz&ȱSi5 z6LP($ arjk`lϱgڋZ8>1퍓gq:{/ z]bӆJ*ˊ[P6z6(ɂg=R$`hd @x^b" 8K R\wX$y}Cw{Iàrvb|`Px<~KzPHMU9f‘^EyZB!*/-ZFbD|Dsޱ PIE4:7$M =i:oU%D"Q.1:^h=aNEڱ}]#LT;%j7JKѹ.5Ǔg.а} O| g-IA@`Dã+_e6F$N QlݴHxl(XMo_?zp$Be5mi2@WwݽPYFiqAQofb2@QA^ѣKRQVP$ttt膵^[筨5zP@skc^n4xeA;Im n,/ oYxb쩯CQE"Q^ ecug/K?LT \|"߽HO9>1l(WΞ]=dX  t>t:])˛*b@Q$Xiǀ(9;"Joe4 ɀL3q=K.D盚t9r+saRҏF>+ǸvIfy\LkSBqޝ͡j=|hчnLKWMn>8.^nYob8I$ 3ABѱm]̆Bƭ64H$,.YGJ9X,v`h*-z'{?;z]yN"kl2rW\!ljѨ +8Լ~n.FWQkꇓ']j^tZ %'#MڝBRR^Z)eg: ߍT*;FCV!Ng/^)O8N˙ oH#ШL,RiT*F>w=m#4]µҢHnIeō9Ңu5l) 9MiQu\.jvUH\nχ]nCEsFp9bd-^D"7^Šr`ыS Nl⡃{(e({3'St.R4V)t:F!O*ښs0/P]y`*8(93$Y۬9˸h)!F6mGrssŅXY*im$HPSUli@ >X 6CҎ(@c}]?khDFJ$3ss186wx}eRKahd,m޽^ǁG*ˊg/^NjkKZձ~;2?h|ժUKtX p:/-SRQɸ"Sb1GO(H8l"J*|`?cRYVLEi1RyOVrOD(F\nϓv`бZf-^y$*hЗغ`?0p`Έ2 }5/8{' t:Jciq \L}]-e+/) :7T&MF^įG8{6T6JREMZz2ѹpKSrl,}q]z8ouNz5R(P)ǝNnN9,fEHd䕣'M s98 P(>hY-.'\L-GWd.锢p=c@ce{0d6ftlbxLH9.S #唸&s-vHdކo؄k׻P*l߲ NC[G7ݽ^Gǹl8۬ x)bѰmbDȑ#[^[)|d NƠ).ȣ xB1p7$VH21ulXMYq3Y&u[6RU^žmTs*p@A4+RR.?vsTF\(s3"aLqG:!K%b1y99Yncu_|,~S*4'ɤJTJed$'W W6 z. MQA.?[lLkA,#:[4 |9$?B*|,;w H^(-. '; EH++odoVm'nCUy)*巷l^w~3꒞ԭToG] ͭgH?|[)*ȣ0?.-jHC#cOzԊ[7o@7ܞ__۬b`EzEث.\ːL/.adyi —LݣЖ# ')/-;H^: u۽ [( uY:(-.j}Kp; ŢQ3_ȿZOt!H ۏn&.KvֺI++7T*J(mV/PaIwV6@J{>fqe=D"Q‘Hf'yp~PY^BQ~nʗ^7-t3ҋ9Y?Xt;A<,˙ ;<)H:/,6Eӷ @V$`lPy׋^eph[6QT9R*ШUNsIkg&BV*g ,ٷV"(:aZ&6VWj5v.en͔\ 5U6cLpz}75gF.'hYtG6V\g"h./Bʄl+Ji5/~ mGGg|ڊkE*P_W;|`lXjţrH$ʦ &&y=}aE&" qN2GA^n6B(B&;LMH$D\m? SyyRҸR鹜 }LwLV~wNZ;j[ l`2\Hg1cc7ei_\iQ׮wiS;0 ^M۷l265BG2 Xt:WŬVHK.5 RO$۵nXZK.@ 5#Hł}']k9[\ )?:rP _^y6m,ݜ쬐hrBsNse; k?q '4cA$K#w=QڞRmV9B$bH)բEI0 zvP8⸰I0U'Kia]VR|~exksF(P$Y@$e G?@Ѱu`vB۬ g e mؓߔ~>뻼˻38FIENDB`ukui-panel-3.0.6.4/plugin-calendar/html/images/zodiac/blue/0000755000175000017500000000000014204636772022045 5ustar fengfengukui-panel-3.0.6.4/plugin-calendar/html/images/zodiac/blue/mouse-white.png0000644000175000017500000001574214204636772025032 0ustar fengfengPNG  IHDRh=A_,IDATx| tTUs*aHRI!a ""* h;!ߵu]{Wm{nV۩EPFA0!IBJMT筿P::s?|7_ @e$ Xk $Iz7j ><xހcx( F(0( ki(wm@(3@<,IdF=7 glƿ : ?^9rD{{"3yP x9,HTICK7!,lsJJJ9x5}ژNgLNNȸx!gjgg[Ԯa_haQ@+-0f̘?dddZZZ%h'6YYttL̠UVbb4iZٳ.#۠n?6ű,{&++kEo h|g(`CVV4ep"++ S[[ر/Xa"AzCDBBB #:q}9 !؜;AglƯ}>u675Y  |k8\w١4GA/^@Hel$IƏ7`C6:=u򤷾/.k^}}M?l[F?~mfKFiӣ=j@7L GG-)*b5aН~o9ы۲i (jM̝>uJ=s+eٚF=*ڪyر.]azqG{ׯ}[e|pU&vL^xEQȈH dcB=}iii.n$%%y\,>c҂?VUUe_e)x v$I BM1t_}aKCCã~ 1uu{>o7o͆j 1M] wo~8@oܸ)Zq)Ĵ4}kk IV?AmBB"< 0uj~ϲOPf `!v,؛կ~\xʷ^.x<{yz^E9wu&5)ɩEyj̬ap{?iOLL ;w 'OQ DGEiRyy9S[SSv҅ %#Q`SRRnIɄ[\Y?A#0$B:SY̒TQϟ#x_ 1.?V{zkSGG,By7k2m}zc0%N'׫e~ii;q:s]0w.>UVO w</AO3E h~l6{ೲy)aq[8{KW4͢t߰W5U|O=4N$.;w~Cch4.D+<OD4$ɇIlܸi3WRRly$l6HNNF5Nh0k֬<#6h$iF4-BF\e.ubNvNBtvvbY/;ڍ=Z*&;hڰq岟O8 H7np VUП=sfˌ3<7NDFFzB_~[eF <«g};a8N(3fnmDȑfsϠ5S^^kp Wj[ZZҴZs\r8;''nΜ°<:)?+>>^^ڰM0NC2=<(!ɘ$+IRC3?q1fpQUUErS ㍎qvvt<D8B999HSUoy%# DQKJJnĈCOCC8q+SA!8nAJ_1P(򗋥[`L:Z,0m@"eL1s2c˗.eEy6+JHH`X_c x JU]q`().v<hoΓ<=O?.3L&!~"!xAW,kop0I~+3CWP:I^rj0, 8$zzAm+PQQ.o[f:e@131qkn7$IؘT[[x >t::(5PSSr9]rlln9Li Gk8l7mH zAB=6m[ Y̲gqq}g_oE6K%G֬XSs˲4j饥'$hUU= %߽MWv*: $Ѻq!E?6@!aMڧ{v'Mz i^E1bxAN6 MӖ`YdL\{WܧywL-E1Pesq!bE{5Aq4M>T0 .BSS[$͸zm=Q(htX p_ Àɓ׬VUnY(ꩮFcc#SQRUU\2ˏ3֮ _)sp (ZՖ=Szх~ ̬̐F9..΁LcCÀ(iӈ40,!,V('( ˥۲e`0cf㙗hWQ]5T+`dYIJ?Uj6,衋Xp80gwh4vree 7~kIs'L^}Aw A_pGhӬV+J5tǝK5AE x)׷Ƈ x={Na0hUU{?c$''{%QRPPf<=xw/PEpoՇw`E/(9$PCَuAh%IZRuIQ ,cer ĩ]!k'U~e=)-񹹒_H"}i3.\t9zxbEO$.8R.TUj}W'ÍlroA 4M&0VpvM6 Ny~ҋPSSn.͓҄&c+l]ݬ((/_~Ԥ @GFF]!%1g;/%jFSgZU l}yWeUUG/LĮ䔔e`9oY٥bfqGG=&h2 M G+eYOQu(?u$kkq`>k񨪪;rƍ[` 'O&&=csѱry~ն刢%/?ߘ0gnVVfKMQԇYA=ªg} 6p4 ?$:誩D\+]$rNSўP Znpdddh˓y.@RG0 btO&K-5;<O !Ec3\ݎl=QQQwϚuMåUYA/]zxvY<@b&2`TYzU虬C?(x^\)^ղʢQfZ-Tc/ظ_i?>7r(Aƥ8r;-Y,uرT]O`΅ %nQQ('!L! H/(AdpTGop`$IznV3| cov׻r8EM;P'!Maw8|u1ݶnS<(rQu YQj$QEokڭ}Vۜ;( ~S:=fr(KsrS^ [[ZA<I+7oL3&8l:0d21߂l6ݍxA渃$f[#5?Bs`Q4))i΢Kz=H(΁{jyALllrFF> ^pa= c:ݫv xڛ555kjjAz(jlt :G233BhǐG.gao6Mzp͢(VHQ~M?(/ᦖ |L%I*D>Łғv!;U ˲ŹF!'| J<`Z,DQ\T@!$nܴ)ge,{riQ5,34M#ISQUU(Jj4e9d2ˆQڨ(6&&b}vGxN͟ ߧNWp "nҤ\(;Z^X;hѫ(&ꊤi˚eE) 2a_ܾ=H/PU!Zn[rCCC25Et>7#pZvNNV06}׮6QAPH?([jzTUU!}Me=õmܕ`Զa?dmRP R$Ir<YX;ia*^(Æ{\NẺkP]]j/xU q& i]j Z3(C@fl6D=8ŋ6Y KU:w IENDB`ukui-panel-3.0.6.4/plugin-calendar/html/images/zodiac/blue/blue-pig.png0000644000175000017500000001657714204636772024277 0ustar fengfengPNG  IHDRiV̮BFIDATxytcY}?O%ےٖw]eri!LzhF@pQ `2@tH@Nw7$f2s&$n6U]hvY!ml[-]*wu}o6ov^~{]v8pxh~|+q1K=lE"4  vtzN4Z ꩪF.Ϝ~-2a9-ýI, {'77w D/Y-\nuVt5}W"=]UUR\4D"aGgE.bb>%G-2la^Ꚛ4 PeKoLZmTԠV+]q8kp/Dٲcn>"l= k:v:)A^JIF#HTP{$bwq9|(999?pH$C\Ntb_tzkVH$zi29]ҽ^L$3tvv9ȣlHG*b2噢afpV)+K16sPyAd2@]{Igغu(@ 6 u&d-;ZȨLLn4|>E M$ueeeTVU099I<K_o/J.ޱXPSS`O~ wc~9rxծ˗~T*:A==#JWTX(f {TWuzmnގbּH,QXX\[[ۜ}LyNx#kA<'ް4l޲03*((Bd}3_vD"~twˎ fo#V$q:C5uuuH[]]C(2 lO/ђ>|{.(B֢.(؝UWPR,Lߗܸ~Hhjڼw(,,4Y-VrA=' ɤy4VdaaegqӦU4 TTV68N6eޮݻyWj1B7vE> I |KRIEe%xs*)YÀxmQYYuO** RwXB$y;]/BTԘ6g;on4:X4FaQEEE f pFbUhZTj*P(W .iMYYj1gҪ*p-'**+M7o9L&~'b?|p?QBJkW?bUUuI(׮^?1~uzzz|g_:|d%׳fq:V$b;} K*!D$I8h|,:at|ȧʪz|X/xfZBx<FFnvtd`0!5\ (^gД JZ̟ /.j1庂BQ"x<=xSOzj1ϔx<ã#_}?yLed6Lw?Ax<Ϋ dRXvbd2I{9D@cSj`0>Ȑ~XJGfI kK@;pJT[%aZJT׋T*EHM}>VD"6py aFS}}@D"N~~q7<|>_Tk$&H"r9呗D13w>N߳]/O'9ydMMMH$ܼh׮\|> ټy13ߛ/D"hF]P@]݆"aEA]ՖXў8ӑjNJgoqgdx;#ra+*e|l-@kjQ(LǏmw_H$eWæFdK2dSc)cqxH$loi3BMeQ8xC,sy~?p x6zU*UUU| BR??sg9HsgόqOU 'ANNb8D<MkjmvdLF8n3Oq;5@~^>@ ,5Rtcii:^[D<ڮt]fzzAvDԍa#ӑ;wB7cO5ot/2J5,.JJK?sGP_&)gކ/MNNh0dzG9 xߺ^5kײ߼R}@k3{>〩j֭ExI&DbP([AP*Τ۰ymo#,q/ Ś Ǐ7⣙9iVQQ}f?ccc\.]/waϝpN:ͥ@ @qc<ʶ3% 5h4%& !e<ܼ}.ܖT"ɸ@ >&Ln^gN&>WTT<6I$Tw'8''--T*5Ν;5Eˎsb1{)--tcSS2ټy˓eoCCvH洤A388 [p83tC4:NoxNoxH̟.D,/]bjʳw O.^errӧNGgGP蕊ʪe^p j4aHp8}L^H$rok4LC*|q9 "G񱏵;w{]!trrr۷X"۷iKk#JeѲMIO']FUD"*!Bʍ?l?ў`0+X5虝 "Lq&Rh4sԔA)2VugֹF8f:Ǭo9c:h8DHGV͎Vn#^|r2[5S[[K8ƙ^`&p0h{67/ZdZ:f{ODbwcӑA"gxxԔ7o0d?rv*.^6fd29d}:hfa|'J+k'H&粉J?WM,1:ꘘw==T*h4V.   m.+c?-qONͱ7###:ywVC<#L^7wò42r-/?FDں:(DcKCCLLLbB&=ԸdM(V*4[ZH [7o9pjN7йl"Bk؈ ϑ ={ȏuzn~$ Rك/)ƍ61,}8k%1=u8ckmMYd8Dį<NjaC[ ؘ}>1d|z(lPňօRL&{<=L&!_Bp7Vb5"C7eZ-y\~mޥӋ$I*A^-//_V0~n4fXfm7o|>hϨiH&ݣe"]vks8LV Siq:<A ӰqjD 0o7{=nR44la#~A@.v)..c3ǹzDNN;Z>-)J#%ں._ZW3tvrf]6p8e.J_Xh4.]]HDڮt-8n$ p|goϞ9 ctypJ7(L~ƍZ2WL=cc+LʀgLf&''wVY>91^,~D"ht,`ƍg< H3tzC07"J%nRلbVsĆB!SgSjR~5::zp9퇉x<Jߖͱ׉D"656R@(jV* SNQ]H+--5gO!iظQ1rv_II)MřI[Ǘ[jD뒒ӎ֝[eoy?[ +Ă |y%NҾeKJKW̥XtV*{ЮwG}:PVV"1HᲲe* A(r/w 5o[a'av1P()-+]ULm`}7]H{Ah߼e뒯]bjåM@~rr1?moiɺ3J"''gǫFRi#imwx!qr>[ |^:I&KG9e j1>}f37/p8 ,)R>I#>M1Μ>EG{ɾ纻o}S^:m5 "HF 4Not$ΎUjHm|$D%3 mt:| %e/`gNtflzo eH&LLLp|'n{t}gtz?,Nox.,V[XTh-+`1 B^/.^j۟ 'Ο4¢sm\z<LNN|7\.ߞPT*C@#G" HHBjD"Dc1b(HϏ;' Tmjl@t$q}3=A559PD"N(ȈuG|ɉLNLT*?xb "3NeH$GVQ^^q X M&g F*\Dj<@3PTz-J$eJ-J L&$-R똆+@')W*+޳ث'&H&?H[V >~1'G U2#ӟVKHgT X,wx<=ljl=e m #pfsN"!8wֵEIm dŬ妭M^Q4?MNN Rp8\H$h4-X/|>[N6|=u0WT Hsu:!tVsI X)-[L/c,3}p:abtR+g=O{zޏ?_Sj1E"{"[M3Ѷ\x׸No8Oj\|)|\Vvo 'caH_}us H$~W@J(`"X><KFSs3uv*&/*@j h ?ӕ>/w`ѸѴ6osK۲LWҰIENDB`ukui-panel-3.0.6.4/plugin-calendar/translation/0000755000175000017500000000000014203402514017752 5ustar fengfengukui-panel-3.0.6.4/plugin-calendar/translation/calendar_zh_CN.ts0000644000175000017500000001720214203402514023156 0ustar fengfeng CalendarActiveLabel Time and Date 时间与日期 Time and Date Setting 时间日期设置 Config panel 设置任务栏 LunarCalendarItem 消防宣传日 志愿者服务日 全国爱眼日 抗战纪念日 LunarCalendarWidget Year Month Today 今天 Sun 周日 Mon 周一 Tue 周二 Wed 周三 Thur 周四 Fri 周五 Sat 周六 解析json文件错误! Sunday 周日 Monday 周一 Tuesday 周二 Wednesday 周三 Thursday 周四 Friday 周五 Saturday 周六 UkuiWebviewDialog Dialog frmLunarCalendarWidget Form 整体样式 红色风格 选中样式 矩形背景 圆形背景 角标背景 图片背景 星期格式 短名称 普通名称 长名称 英文名称 显示农历 ukui-panel-3.0.6.4/plugin-calendar/ukuicalendar.cpp0000644000175000017500000005417714204636772020625 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2012-2013 Razor team * Authors: * Kuzma Shapran * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "ukuicalendar.h" #include #include #include #include #include #include #include #include #include #include #include #include "../panel/pluginsettings.h" #include #include #include #include #include #include #include #include #include #include #define CALENDAR_HEIGHT (46) #define CALENDAR_WIDTH (104) #define WEBVIEW_WIDTH (454) #define WEBVIEW_MAX_HEIGHT (704) #define WEBVIEW_MIN_HEIGHT (600) #define POPUP_BORDER_SPACING 4 #define HOUR_SYSTEM_CONTROL "org.ukui.control-center.panel.plugins" #define HOUR_SYSTEM_24_Horizontal "hh:mm ddd yyyy/MM/dd" #define HOUR_SYSTEM_24_Vertical "hh:mm ddd MM/dd" #define HOUR_SYSTEM_12_Horizontal "Ahh:mm ddd yyyy/MM/dd" #define HOUR_SYSTEM_12_Vertical "Ahh:mm ddd MM/dd" #define CURRENT_DATE "yyyy/MM/dd dddd" #define HOUR_SYSTEM_24_Horizontal_CN "hh:mm ddd yyyy-MM-dd" #define HOUR_SYSTEM_24_Vertical_CN "hh:mm ddd MM-dd" #define HOUR_SYSTEM_12_Horizontal_CN "Ahh:mm ddd yyyy-MM-dd" #define HOUR_SYSTEM_12_Vertical_CN "Ahh:mm ddd MM-dd" #define CURRENT_DATE_CN "yyyy-MM-dd dddd" #define HOUR_SYSTEM_KEY "hoursystem" #define SYSTEM_FONT_SIZE "systemFontSize" #define SYSTEM_FONT_SET "org.ukui.style" QString calendar_version; extern UkuiWebviewDialogStatus status; IndicatorCalendar::IndicatorCalendar(const IUKUIPanelPluginStartupInfo &startupInfo): QWidget(), IUKUIPanelPlugin(startupInfo), mTimer(new QTimer(this)), mCheckTimer(new QTimer(this)), mUpdateInterval(1), mbActived(false), mbHasCreatedWebView(false), mViewWidht(WEBVIEW_WIDTH), mViewHeight(0), mWebViewDiag(NULL) { translator(); mMainWidget = new QWidget(); mContent = new CalendarActiveLabel(this); mWebViewDiag = new UkuiWebviewDialog(this); QVBoxLayout *borderLayout = new QVBoxLayout(this); mLayout = new UKUi::GridLayout(mMainWidget); setLayout(mLayout); mLayout->setContentsMargins(0, 0, 0, 0); mLayout->setSpacing(0); mLayout->setAlignment(Qt::AlignCenter); mLayout->addWidget(mContent); mContent->setObjectName(QLatin1String("WorldClockContent")); mContent->setAlignment(Qt::AlignCenter); mTimer->setTimerType(Qt::PreciseTimer); const QByteArray id(HOUR_SYSTEM_CONTROL); if(QGSettings::isSchemaInstalled(id)){ gsettings = new QGSettings(id); connect(gsettings, &QGSettings::changed, this, [=] (const QString &keys){ updateTimeText(); }); if(QString::compare(gsettings->get("date").toString(),"cn")) { hourSystem_24_horzontal=HOUR_SYSTEM_24_Horizontal_CN; hourSystem_24_vartical=HOUR_SYSTEM_24_Vertical_CN; hourSystem_12_horzontal=HOUR_SYSTEM_12_Horizontal_CN; hourSystem_12_vartical=HOUR_SYSTEM_12_Vertical_CN; current_date=CURRENT_DATE_CN; } else { hourSystem_24_horzontal=HOUR_SYSTEM_24_Horizontal; hourSystem_24_vartical=HOUR_SYSTEM_24_Vertical; hourSystem_12_horzontal=HOUR_SYSTEM_12_Horizontal; hourSystem_12_vartical=HOUR_SYSTEM_12_Vertical; current_date=CURRENT_DATE; } } else { hourSystem_24_horzontal=HOUR_SYSTEM_24_Horizontal_CN; hourSystem_24_vartical=HOUR_SYSTEM_24_Vertical_CN; hourSystem_12_horzontal=HOUR_SYSTEM_12_Horizontal_CN; hourSystem_12_vartical=HOUR_SYSTEM_12_Vertical_CN; current_date=CURRENT_DATE_CN; } //六小时会默认刷新时间 mCheckTimer->setInterval(60*60*1000); connect(mCheckTimer, &QTimer::timeout, [this]{checkUpdateTime();}); mCheckTimer->start(); connect(mTimer, &QTimer::timeout, [this]{checkUpdateTime();}); mTimer->start(1000); const QByteArray _id(SYSTEM_FONT_SET); fgsettings = new QGSettings(_id); connect(fgsettings, &QGSettings::changed, this, [=] (const QString &keys){ if(keys == SYSTEM_FONT_SIZE){ updateTimeText(); } }); connect(mWebViewDiag, SIGNAL(deactivated()), SLOT(hidewebview())); if(QGSettings::isSchemaInstalled(id)) { connect(gsettings, &QGSettings::changed, this, [=] (const QString &key) { if (key == HOUR_SYSTEM_KEY) { if(gsettings->keys().contains("hoursystem")) { hourSystemMode=gsettings->get("hoursystem").toString(); } else hourSystemMode=24; } if(key == "calendar") { mbHasCreatedWebView = false; initializeCalendar(); } if(key == "firstday") { qDebug()<<"key == firstday"; mbHasCreatedWebView = false; initializeCalendar(); } if(key == "date") { if(gsettings->keys().contains("date")) { if(QString::compare(gsettings->get("date").toString(),"cn")) { hourSystem_24_horzontal=HOUR_SYSTEM_24_Horizontal_CN; hourSystem_24_vartical=HOUR_SYSTEM_24_Vertical_CN; hourSystem_12_horzontal=HOUR_SYSTEM_12_Horizontal_CN; hourSystem_12_vartical=HOUR_SYSTEM_12_Vertical_CN; current_date=CURRENT_DATE_CN; } else { hourSystem_24_horzontal=HOUR_SYSTEM_24_Horizontal; hourSystem_24_vartical=HOUR_SYSTEM_24_Vertical; hourSystem_12_horzontal=HOUR_SYSTEM_12_Horizontal; hourSystem_12_vartical=HOUR_SYSTEM_12_Vertical; current_date=CURRENT_DATE; } } updateTimeText(); } }); } connect(mContent,&CalendarActiveLabel::pressTimeText,[=]{CalendarWidgetShow();}); // initializeCalendar(); setTimeShowStyle(); mContent->setWordWrap(true); ListenGsettings *m_ListenGsettings = new ListenGsettings(); QObject::connect(m_ListenGsettings,&ListenGsettings::iconsizechanged,[this]{updateTimeText();}); QObject::connect(m_ListenGsettings,&ListenGsettings::panelpositionchanged,[this]{updateTimeText();}); updateTimeText(); QTimer::singleShot(10000,[this] { updateTimeText();}); //读取配置文件中CalendarVersion 的值 QString filename ="/usr/share/ukui/ukui-panel/panel-commission.ini"; QSettings m_settings(filename, QSettings::IniFormat); m_settings.setIniCodec("UTF-8"); m_settings.beginGroup("Calendar"); calendar_version = m_settings.value("CalendarVersion", "").toString(); if (calendar_version.isEmpty()) { calendar_version = "old"; } m_settings.endGroup(); //监听手动更改时间,后期找到接口进行替换 QTimer::singleShot(1000,this,[=](){ListenForManualSettingTime();}); } IndicatorCalendar::~IndicatorCalendar() { if(mMainWidget != NULL) { mMainWidget->deleteLater(); } if(mWebViewDiag != NULL) { mWebViewDiag->deleteLater(); } if(mContent != NULL) { mContent->deleteLater(); } gsettings->deleteLater(); fgsettings->deleteLater(); } void IndicatorCalendar::translator(){ m_translator = new QTranslator(this); QString locale = QLocale::system().name(); if (locale == "zh_CN"){ if (m_translator->load(QM_INSTALL)) qApp->installTranslator(m_translator); else qDebug() < pathresult=delaytime.split(":"); int second=pathresult.at(2).toInt(); if(second==0){ mTimer->setInterval(60*1000); }else{ mTimer->setInterval((60+1-second)*1000); } timeState = tzNow.toString("hh:mm ddd yyyy-MM-dd"); updateTimeText(); } void IndicatorCalendar::updateTimeText() { QDateTime tzNow = QDateTime::currentDateTime(); QString str; QByteArray id(HOUR_SYSTEM_CONTROL); if(QGSettings::isSchemaInstalled(id)) { QStringList keys = gsettings->keys(); if(keys.contains("hoursystem")) hourSystemMode=gsettings->get("hoursystem").toString(); } else { hourSystemMode = 24; } if(!QString::compare("24",hourSystemMode)) { if(panel()->isHorizontal()) str=tzNow.toString(hourSystem_24_horzontal); else str=tzNow.toString(hourSystem_24_vartical); } else { if(panel()->isHorizontal()) { str=tzNow.toString(hourSystem_12_horzontal); } else { str = tzNow.toString(hourSystem_12_vartical); str.replace("AM","AM "); str.replace("PM","PM "); } } QString style; int font_size = fgsettings->get(SYSTEM_FONT_SIZE).toInt(); if(font_size>14) font_size=14; if(font_size<12) font_size=12; style.sprintf( //正常状态样式 "QLabel{" "border-width: 0px;" //边框宽度像素 "border-radius: 6px;" //边框圆角半径像素 "font-size: %dpx;" //字体,字体大小 "padding: 0px;" //填衬 "text-align:center;" //文本居中 "}" //鼠标悬停样式 "QLabel:hover{" "background-color:rgba(190,216,239,20%%);" "border-radius:6px;" //边框圆角半径像素 "}" //鼠标按下样式 "QLabel:pressed{" "background-color:rgba(190,216,239,12%%);" "}", font_size); mContent->setStyleSheet(style); mContent->setText(str); } /*when widget is loading need initialize here*/ void IndicatorCalendar::initializeCalendar() { QByteArray id(HOUR_SYSTEM_CONTROL); CalendarShowMode showCalendar = defaultMode; QString lunarOrsolar; QString firstDay; int iScreenHeight = QApplication::screens().at(0)->size().height() - panel()->panelSize(); if(iScreenHeight > WEBVIEW_MAX_HEIGHT) { mViewHeight = WEBVIEW_MAX_HEIGHT; } else { mViewHeight = WEBVIEW_MIN_HEIGHT; } if(QGSettings::isSchemaInstalled(id)) { if(!gsettings) { qDebug()<<"get gsetting error!!!"; return; } if(gsettings->keys().contains("calendar")) { lunarOrsolar= gsettings->get("calendar").toString(); } if(gsettings->keys().contains("firstday")) { firstDay= gsettings->get("firstday").toString(); } if (QLocale::system().name() == "zh_CN") { if(lunarOrsolar == "lunar") { if(firstDay == "sunday") { showCalendar = lunarSunday; } else if(firstDay == "monday") { showCalendar = lunarMonday; } if(iScreenHeight > WEBVIEW_MAX_HEIGHT) { mViewHeight = WEBVIEW_MAX_HEIGHT; } else { mViewHeight = WEBVIEW_MIN_HEIGHT; } } else if(lunarOrsolar == "solarlunar") { if(firstDay == "sunday") { showCalendar = solarSunday; } else if(firstDay == "monday") { showCalendar = solarMonday; } mViewHeight = WEBVIEW_MIN_HEIGHT; } } else// for internaitional { if(firstDay == "sunday") { showCalendar = solarSunday; } else if(firstDay == "monday") { showCalendar = solarMonday; } mViewHeight = WEBVIEW_MIN_HEIGHT; } } if(mWebViewDiag != NULL ) { if(!mbHasCreatedWebView) { mWebViewDiag->creatwebview(showCalendar,panel()->panelSize()); mbHasCreatedWebView = true; } } } void IndicatorCalendar::CalendarWidgetShow() { if(mWebViewDiag != NULL ) { mViewHeight = WEBVIEW_MAX_HEIGHT; QByteArray id(HOUR_SYSTEM_CONTROL); if(QGSettings::isSchemaInstalled(id)) { if(gsettings->get("calendar").toString() == "solarlunar") mViewHeight = WEBVIEW_MIN_HEIGHT; } if (QLocale::system().name() != "zh_CN") mViewHeight = WEBVIEW_MIN_HEIGHT; int iScreenHeight = QApplication::screens().at(0)->size().height() - panel()->panelSize(); if (iScreenHeight < WEBVIEW_MAX_HEIGHT) { mViewHeight = iScreenHeight; if (iScreenHeight >= WEBVIEW_MIN_HEIGHT) mViewHeight = WEBVIEW_MIN_HEIGHT;; } if(qgetenv("XDG_SESSION_TYPE")=="wayland") mWebViewDiag->setGeometry(calculatePopupWindowPos(QSize(mViewWidht+POPUP_BORDER_SPACING,mViewHeight+POPUP_BORDER_SPACING))); else modifyCalendarWidget(); #if 0 mWebViewDiag->show(); mWebViewDiag->activateWindow(); if(!mbActived) { mWebViewDiag->setHidden(false); // mWebViewDiag->webview()->reload(); mbActived = true; } else { mWebViewDiag->setHidden(true); // mWebViewDiag->webview()->reload(); mbActived = false; } #endif if(status==ST_HIDE) { status = ST_SHOW; mWebViewDiag->setHidden(false); } else { status = ST_HIDE; mWebViewDiag->setHidden(true); } } } /** * @brief IndicatorCalendar::activated * @param reason * 如下两种方式也可以设置位置,由于ui问题弃用 * 1.mWebViewDiag->setGeometry(calculatePopupWindowPos(QSize(mViewWidht+POPUP_BORDER_SPACING,mViewHeight+POPUP_BORDER_SPACING))); * 2. // QRect screen = QApplication::desktop()->availableGeometry(); // switch (panel()->position()) { // case IUKUIPanel::PositionBottom: // mWebViewDiag->move(screen.width()-mViewWidht-POPUP_BORDER_SPACING,screen.height()-mViewHeight-POPUP_BORDER_SPACING); // break; // case IUKUIPanel::PositionTop: // mWebViewDiag->move(screen.width()-mViewWidht-POPUP_BORDER_SPACING,panel()->panelSize()+POPUP_BORDER_SPACING); // break; // case IUKUIPanel::PositionLeft: // mWebViewDiag->move(panel()->panelSize()+POPUP_BORDER_SPACING,screen.height()-mViewHeight-POPUP_BORDER_SPACING); // break; // default: // mWebViewDiag->setGeometry(calculatePopupWindowPos(QSize(mViewWidht+POPUP_BORDER_SPACING,mViewHeight+POPUP_BORDER_SPACING))); // break; // } */ void IndicatorCalendar::hidewebview() { mWebViewDiag->setHidden(true); mbActived = false; } void IndicatorCalendar::realign() { setTimeShowStyle(); } void IndicatorCalendar::setTimeShowStyle() { int size = panel()->panelSize() - 3; if (size > 0) { if(panel()->isHorizontal()) { mContent->setFixedSize(CALENDAR_WIDTH, size); } else { mContent->setFixedSize(size, CALENDAR_WIDTH); } } } /** * @brief IndicatorCalendar::modifyCalendarWidget * 任务栏上弹出窗口的位置标准为距离屏幕边缘及任务栏边缘分别为4像素 */ void IndicatorCalendar::modifyCalendarWidget() { int totalHeight = qApp->primaryScreen()->size().height() + qApp->primaryScreen()->geometry().y(); int totalWidth = qApp->primaryScreen()->size().width() + qApp->primaryScreen()->geometry().x(); switch (panel()->position()) { case IUKUIPanel::PositionBottom: mWebViewDiag->setGeometry(totalWidth-mViewWidht-4,totalHeight-panel()->panelSize()-mViewHeight-4,mViewWidht,mViewHeight); break; case IUKUIPanel::PositionTop: mWebViewDiag->setGeometry(totalWidth-mViewWidht-4,qApp->primaryScreen()->geometry().y()+panel()->panelSize()+4,mViewWidht,mViewHeight); break; case IUKUIPanel::PositionLeft: mWebViewDiag->setGeometry(qApp->primaryScreen()->geometry().x()+panel()->panelSize()+4,totalHeight-mViewHeight-4,mViewWidht,mViewHeight); break; case IUKUIPanel::PositionRight: mWebViewDiag->setGeometry(totalWidth-panel()->panelSize()-mViewWidht-4,totalHeight-mViewHeight-4,mViewWidht,mViewHeight); break; default: mWebViewDiag->setGeometry(qApp->primaryScreen()->geometry().x()+panel()->panelSize()+4,totalHeight-mViewHeight,mViewWidht,mViewHeight); break; } } void IndicatorCalendar::ListenForManualSettingTime(){ mProcess=new QProcess(this); QString command="journalctl -u systemd-timedated.service -f"; mProcess->setReadChannel(QProcess::StandardOutput); mProcess->start(command); mProcess->startDetached(command); connect(mProcess,&QProcess::readyReadStandardOutput,this,[=](){ updateTimeText(); }); } CalendarActiveLabel::CalendarActiveLabel(IUKUIPanelPlugin *plugin, QWidget *parent) : QLabel(parent), mPlugin(plugin), mInterface(new QDBusInterface(SERVICE,PATH,INTERFACE,QDBusConnection::sessionBus(),this)) { w = new frmLunarCalendarWidget(); connect(w,&frmLunarCalendarWidget::yijiChangeDown, this, [=] (){ changeHight = 0; changeWidowpos(); }); connect(w,&frmLunarCalendarWidget::yijiChangeUp, this, [=] (){ changeHight = 52; changeWidowpos(); }); QTimer::singleShot(1000,[this] {setToolTip(tr("Time and Date")); }); } void CalendarActiveLabel::mousePressEvent(QMouseEvent *event) { if (Qt::LeftButton == event->button()){ if(calendar_version == "old"){ Q_EMIT pressTimeText(); } else { //点击时间标签日历隐藏,特殊处理 if(w->isHidden()){ changeWidowpos(); }else{ w->hide(); } } // mInterface->call("ShowCalendar"); } } void CalendarActiveLabel::changeWidowpos() { int totalHeight = qApp->primaryScreen()->size().height() + qApp->primaryScreen()->geometry().y(); int totalWidth = qApp->primaryScreen()->size().width() + qApp->primaryScreen()->geometry().x(); switch (mPlugin->panel()->position()) { case IUKUIPanel::PositionBottom: w->setGeometry(totalWidth-mViewWidht-4,totalHeight-mPlugin->panel()->panelSize()-mViewHeight-4-changeHight,mViewWidht,mViewHeight); break; case IUKUIPanel::PositionTop: w->setGeometry(totalWidth-mViewWidht-4,qApp->primaryScreen()->geometry().y()+mPlugin->panel()->panelSize()+4,mViewWidht,mViewHeight); break; case IUKUIPanel::PositionLeft: w->setGeometry(qApp->primaryScreen()->geometry().x()+mPlugin->panel()->panelSize()+4,totalHeight-mViewHeight-4-changeHight,mViewWidht,mViewHeight); break; case IUKUIPanel::PositionRight: w->setGeometry(totalWidth-mPlugin->panel()->panelSize()-mViewWidht-4,totalHeight-mViewHeight-4-changeHight,mViewWidht,mViewHeight); break; default: w->setGeometry(qApp->primaryScreen()->geometry().x()+mPlugin->panel()->panelSize()+4,totalHeight-mViewHeight,mViewWidht,mViewHeight); break; } w->show(); } void CalendarActiveLabel::contextMenuEvent(QContextMenuEvent *event) { QMenu *menuCalender=new QMenu(this); menuCalender->setAttribute(Qt::WA_DeleteOnClose); menuCalender->addAction(QIcon::fromTheme("document-page-setup-symbolic"), tr("Time and Date Setting"), this, SLOT(setControlTime()) ); menuCalender->setGeometry(mPlugin->panel()->calculatePopupWindowPos(mapToGlobal(event->pos()), menuCalender->sizeHint())); menuCalender->show(); } void CalendarActiveLabel::setControlTime() { QProcess *process =new QProcess(this); process->start( "bash", QStringList() << "-c" << "dpkg -l | grep ukui-control-center"); process->waitForFinished(); QString strResult = process->readAllStandardOutput() + process->readAllStandardError(); if (-1 != strResult.indexOf("3.0")) { QProcess::startDetached(QString("ukui-control-center -t")); } else { QProcess::startDetached(QString("ukui-control-center -m Date")); } } ukui-panel-3.0.6.4/panel/0000755000175000017500000000000014204636776013472 5ustar fengfengukui-panel-3.0.6.4/panel/pluginmoveprocessor.h0000644000175000017500000000454314203402514017752 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2012 Razor team * Authors: * Alexander Sokoloff * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef PLUGINMOVEPROCESSOR_H #define PLUGINMOVEPROCESSOR_H #include #include #include #include "plugin.h" #include "ukuipanelglobals.h" class UKUIPanelLayout; class QLayoutItem; class UKUI_PANEL_API PluginMoveProcessor : public QWidget { Q_OBJECT public: explicit PluginMoveProcessor(UKUIPanelLayout *layout, Plugin *plugin); ~PluginMoveProcessor(); Plugin *plugin() const { return mPlugin; } signals: void finished(); public slots: void start(); protected: void mouseMoveEvent(QMouseEvent *event); void mousePressEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event); void keyPressEvent(QKeyEvent *event); private slots: void doStart(); void doFinish(bool cancel); private: enum MarkType { TopMark, BottomMark, LeftMark, RightMark }; struct MousePosInfo { int index; QLayoutItem *item; bool after; }; UKUIPanelLayout *mLayout; Plugin *mPlugin; int mDestIndex; MousePosInfo itemByMousePos(const QPoint mouse) const; void drawMark(QLayoutItem *item, MarkType markType); }; class UKUI_PANEL_API CursorAnimation: public QVariantAnimation { Q_OBJECT public: void updateCurrentValue(const QVariant &value) { QCursor::setPos(value.toPoint()); } }; #endif // PLUGINMOVEPROCESSOR_H ukui-panel-3.0.6.4/panel/panelpluginsmodel.h0000644000175000017500000003172214203402514017346 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2011 Razor team * Authors: * Alexander Sokoloff * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef PANELPLUGINSMODEL_H #define PANELPLUGINSMODEL_H #include #include namespace UKUi { class PluginInfo; struct PluginData; } class UKUIPanel; class Plugin; /*! * \brief The PanelPluginsModel class implements the Model part of the * Qt Model/View architecture for the Plugins, i.e. it is the interface * to access the Plugin data associated with this Panel. The * PanelPluginsModel takes care for read-access as well as changes * like adding, removing or moving Plugins. */ class PanelPluginsModel : public QAbstractListModel { Q_OBJECT public: PanelPluginsModel(UKUIPanel * panel, QString const & namesKey, QStringList const & desktopDirs, QObject * parent = nullptr); ~PanelPluginsModel(); /*! * \brief rowCount returns the number of Plugins. It overrides/implements * QAbstractListModel::rowCount(). * \param parent The parameter parent should be omitted to get the number of * Plugins. If it is given and a valid model index, the method returns 0 * because PanelPluginsModel is not a hierarchical model. */ virtual int rowCount(const QModelIndex & parent = QModelIndex()) const override; /*! * \brief data returns the Plugin data as defined by the Model/View * architecture. The Plugins itself can be accessed with the role * Qt::UserRole but they can also be accessed by the methods plugins(), * pluginByName() and pluginByID(). This method overrides/implements * QAbstractListModel::data(). * \param index should be a valid model index to determine the Plugin * that should be read. * \param role The Qt::ItemDataRole to determine what kind of data should * be read, can be one of the following: * 1. Qt::DisplayRole to return a string that describes the Plugin. * 2. Qt::DecorationRole to return an icon for the Plugin. * 3. Qt::UserRole to return a Plugin*. * \return The data as determined by index and role. */ virtual QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const override; /*! * \brief flags returns the item flags for the given model index. For * all Plugins, this is the same: * Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemNeverHasChildren. */ virtual Qt::ItemFlags flags(const QModelIndex & index) const override; /*! * \brief pluginNames returns a list of names for all the Plugins in * this panel. The names are not the human-readable names but the names * that are used to identify the Plugins, e.g. in the config files. These * names can be used in the method pluginByName() to get a corresponding * Plugin. * * The plugin names are normally chosen to be equal to the * filename of the corresponding *.desktop-file. If multiple instances * of a single plugin-type are created, their names are created by * appending increasing numbers, e.g. 'mainmenu' and 'mainmenu2'. * * \sa findNewPluginSettingsGroup */ QStringList pluginNames() const; /*! * \brief plugins returns a list of Plugins in this panel. */ QList plugins() const; /*! * \brief pluginByName gets a Plugin by its name. * \param name is the name of the plugin as it is used in the * config files. A list of names can be retrieved with the * method pluginNames(). * \return the Plugin with the given name. * * \sa pluginNames */ Plugin *pluginByName(QString name) const; /*! * \brief pluginByID gets a Plugin by its ID. * \param id is the *.desktop-file-ID of the plugin which in turn is the * QFileInfo::completeBaseName() of the desktop-file, e.g. "mainmenu". * * As these IDs are chosen according to the corresponding * desktop-file, these IDs are not unique. If multiple * instances of a single plugin-type are created, they share * the same ID in this sense. Then, this method will return * the first plugin of the given type. * \return the first Plugin found with the given ID. */ Plugin const *pluginByID(QString id) const; /*! * \brief movePlugin moves a Plugin in the underlying data. * * This method is useful whenever a Plugin should be moved several * positions at once. If a Plugin should only be moved one position * up or down, consider using onMovePluginUp or onMovePluginDown. * * \param plugin Plugin that has been moved * \param nameAfter name of the Plugin that should be located after * the moved Plugin after the move operation, so this parameter * determines the new position of plugin. If an empty string is * given, plugin will be moved to the end of the list. * * \note This method is especially useful for drag and drop reordering. * Therefore, it will be called whenever the user moves a Plugin in * the panel ("Move Plugin" in the context menu of the panel). * * \sa onMovePluginUp, onMovePluginDown */ void movePlugin(Plugin * plugin, QString const & nameAfter); signals: /*! * \brief pluginAdded gets emitted whenever a new Plugin is added * to the panel. */ void pluginAdded(Plugin * plugin); /*! * \brief pluginRemoved gets emitted whenever a Plugin is removed. * \param plugin The Plugin that was removed. This could be a nullptr. */ void pluginRemoved(Plugin * plugin); /*! * \brief pluginMoved gets emitted whenever a Plugin is moved. * * This signal gets emitted in movePlugin, onMovePluginUp and * onMovePluginDown. * * \param plugin The Plugin that was moved. This could be a nullptr. * * \sa pluginMovedUp */ void pluginMoved(Plugin * plugin); //plugin can be nullptr in case of move of not loaded plugin /*! * \brief pluginMovedUp gets emitted whenever a Plugin is moved a single * slot upwards. * * When a Plugin is moved a single slot upwards, this signal will be * emitted additionally to the pluginMoved signal so that two signals * get emitted. * * If a Plugin is moved downwards, that Plugin will swap places with * the following Plugin so that the result equals moving the following * Plugin a single slot upwards. So, whenever two adjacent Plugins * swap their places, this signal gets emitted with the Plugin that * moves upwards as parameter. * * For simplified use, only this signal is implemented. There is no * similar pluginMovedDown-signal. * * This signal gets emitted from onMovePluginUp and onMovePluginDown. * * \param plugin The Plugin that moved a slot upwards. * * \sa pluginMoved */ void pluginMovedUp(Plugin * plugin); public slots: /*! * \brief addPlugin Adds a new Plugin to the model. * * \param desktopFile The PluginInfo (which inherits XdgDesktopFile) * for the Plugin that should be added. * * \note AddPluginDialog::pluginSelected is connected to this slot. */ void addPlugin(const UKUi::PluginInfo &desktopFile); /*! * \brief removePlugin Removes a Plugin from the model. * * The Plugin to remove is identified by the QObject::sender() method * when the slot is called. Therefore, this method should only be called * by connecting a signal that a Plugin will emit to this slot. * Otherwise, nothing will happen. * * \note Plugin::remove is connected to this slot as soon as the * Plugin is loaded in the PanelPluginsModel. */ void removePlugin(); // slots for configuration dialog /*! * \brief onMovePluginUp Moves the Plugin corresponding to the given * model index a slot upwards. * * \note The 'Up' button in the configuration widget is connected to this * slot. */ void onMovePluginUp(QModelIndex const & index); /*! * \brief onMovePluginDown Moves the Plugin corresponding to the given * model index a slot downwards. * * \note The 'Down' button in the configuration widget is connected to this * slot. */ void onMovePluginDown(QModelIndex const & index); /*! * \brief onConfigurePlugin If the Plugin corresponding to the given * model index has a config dialog (checked via the flag * IUKUIPanelPlugin::HaveConfigDialog), this method shows * it by calling plugin->showConfigureDialog(). * * \note The 'Configure' button in the configuration widget is connected to * this slot. */ void onConfigurePlugin(QModelIndex const & index); /*! * \brief onRemovePlugin Removes the Plugin corresponding to the given * model index from the Model. * * \note The 'Remove' button in the configuration widget is connected to * this slot. */ void onRemovePlugin(QModelIndex const & index); private: /*! * \brief pluginslist_t is the data type used for mPlugins which stores * all the Plugins. * * \sa mPlugins */ typedef QList > > pluginslist_t; private: /*! * \brief loadPlugins Loads all the Plugins. * \param desktopDirs These directories are scanned for corresponding * .desktop-files which are necessary to load the plugins. */ void loadPlugins(QStringList const & desktopDirs); /*! * \brief loadPlugin Loads a Plugin and connects signals and slots. * \param desktopFile The desktop file that specifies how to load the * Plugin. * \param settingsGroup QString which specifies the settings group. This * will only be redirected to the Plugin so that it knows how to read * its settings. * \return A QPointer to the Plugin that was loaded. */ QPointer loadPlugin(UKUi::PluginInfo const & desktopFile, QString const & settingsGroup); /*! * \brief findNewPluginSettingsGroup Creates a name for a new Plugin * that is not yet present in the settings file. Whenever multiple * instances of a single Plugin type are created, they have to be * distinguished by this name. * * The first Plugin of a given type will be named like the type, e.g. * "mainmenu". If a name is already present, this method tries to * find a free name by appending increasing integers (starting with 2), * e.g. "mainmenu2". If, for example, only "mainmenu2" exists because * "mainmenu" was deleted, "mainmenu" would be returned. So, the method * always finds the first suitable name that is not yet present in the * settings file. * \param pluginType Type of the Plugin. * \return The created name for the Plugin. */ QString findNewPluginSettingsGroup(const QString &pluginType) const; /*! * \brief isIndexValid Checks if a given model index is valid for the * underlying data (column 0, row lower than number of Plugins and * so on). */ bool isIndexValid(QModelIndex const & index) const; /*! * \brief removePlugin Removes a given Plugin from the model. */ void removePlugin(pluginslist_t::iterator plugin); /*! * \brief mNamesKey The key to the settings-entry that stores the * names of the Plugins in a panel. Set upon creation, passed as * a parameter by the panel. */ const QString mNamesKey; /*! * \brief mPlugins Stores all the Plugins. * * mPlugins is a QList of elements while each element corresponds to a * single Plugin. Each element is a QPair of a QString and a QPointer * while the QPointer points to a Plugin. * * To access the elements, you can use indexing or an iterator on the * list. For each element p, p.first is the name of the Plugin as it * is used in the configuration files, p.second.data() is the Plugin. * * \sa pluginslist_t */ pluginslist_t mPlugins; /*! * \brief mPanel Stores a reference to the UKUIPanel. */ UKUIPanel * mPanel; }; Q_DECLARE_METATYPE(Plugin const *) #endif // PANELPLUGINSMODEL_H ukui-panel-3.0.6.4/panel/highlight-effect.cpp0000644000175000017500000003304214203402514017355 0ustar fengfeng/* * Qt5-UKUI's Library * * Copyright (C) 2020, Tianjin KYLIN Information Technology Co., Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this library. If not, see . * * Authors: Yue Lan * */ #include "highlight-effect.h" #include #include #include #include #include #include #include #include #include #include #define TORLERANCE 36 static QColor symbolic_color = Qt::gray; void HighLightEffect::setSkipEffect(QWidget *w, bool skip) { w->setProperty("skipHighlightIconEffect", skip); } bool HighLightEffect::isPixmapPureColor(const QPixmap &pixmap) { QImage img = pixmap.toImage(); bool init = false; int red = 0; int green = 0; int blue = 0; qreal variance = 0; qreal mean = 0; qreal standardDeviation = 0; QVector pixels; bool isPure = true; bool isFullyPure = true; for (int x = 0; x < img.width(); x++) { for (int y = 0; y < img.height(); y++) { auto color = img.pixelColor(x, y); if (color.alpha() != 0) { int hue = color.hue(); pixels< 0 || dg > 0 || db > 0) { isFullyPure = false; } } if (!same) { if (isPure || isFullyPure) { isPure = false; isFullyPure = false; break; } } } } } } if (isPure) return true; mean = mean/pixels.count(); for (auto hue : pixels) { variance += (hue - mean)*(hue - mean); } standardDeviation = qSqrt(variance/pixels.count()); isFullyPure = standardDeviation == 0 || variance == 0; isPure = standardDeviation < 1 || variance == 0; return isPure; } bool HighLightEffect::setMenuIconHighlightEffect(QMenu *menu, bool set, HighLightEffect::EffectMode mode) { if (!menu) return false; menu->setProperty("useIconHighlightEffect", set); menu->setProperty("iconHighlightEffectMode", mode); return true; } bool HighLightEffect::setViewItemIconHighlightEffect(QAbstractItemView *view, bool set, HighLightEffect::EffectMode mode) { if (!view) return false; view->viewport()->setProperty("useIconHighlightEffect", set); view->viewport()->setProperty("iconHighlightEffectMode", mode); return true; } bool HighLightEffect::setButtonIconHighlightEffect(QAbstractButton *button, bool set, EffectMode mode) { if (!button) return false; button->setProperty("useIconHighlightEffect", set); button->setProperty("iconHighlightEffectMode", mode); return true; } bool HighLightEffect::isWidgetIconUseHighlightEffect(const QWidget *w) { if (w) { return w->property("useIconHighlightEffect").toBool(); } return false; } void HighLightEffect::setSymoblicColor(const QColor &color) { qApp->setProperty("symbolicColor", color); symbolic_color = color; } void HighLightEffect::setWidgetIconFillSymbolicColor(QWidget *widget, bool fill) { widget->setProperty("fillIconSymbolicColor", fill); } const QColor HighLightEffect::getCurrentSymbolicColor() { QIcon symbolic = QIcon::fromTheme("nm-device-wired"); QPixmap pix = symbolic.pixmap(QSize(16, 16)); QImage img = pix.toImage(); for (int x = 0; x < img.width(); x++) { for (int y = 0; y < img.height(); y++) { QColor color = img.pixelColor(x, y); if (color.alpha() > 0) { symbolic_color = color; return color; } } } return symbolic_color; } QPixmap HighLightEffect::generatePixmap(const QPixmap &pixmap, const QStyleOption *option, const QWidget *widget, bool force, EffectMode mode) { if (pixmap.isNull()) return pixmap; if (widget) { if (widget->property("skipHighlightIconEffect").isValid()) { bool skipEffect = widget->property("skipHighlightIconEffect").toBool(); if (skipEffect) return pixmap; } } bool isPurePixmap = isPixmapPureColor(pixmap); if (force) { if (!isPurePixmap) return pixmap; QPixmap target = pixmap; QPainter p(&target); p.setRenderHint(QPainter::Antialiasing); p.setRenderHint(QPainter::SmoothPixmapTransform); p.setCompositionMode(QPainter::CompositionMode_SourceIn); if (option->state & QStyle::State_MouseOver || option->state & QStyle::State_Selected || option->state & QStyle::State_On || option->state & QStyle::State_Sunken) { p.fillRect(target.rect(), option->palette.highlightedText()); } else { if (mode == BothDefaultAndHighlit) p.fillRect(target.rect(), option->palette.dark()); } //p.end(); return target; } if (widget) { if (isWidgetIconUseHighlightEffect(widget)) { bool fillIconSymbolicColor = false; if (widget->property("fillIconSymbolicColor").isValid()) { fillIconSymbolicColor = widget->property("fillIconSymbolicColor").toBool(); } if (widget->property("iconHighlightEffectMode").isValid()) { mode = qvariant_cast(widget->property("iconHighlightEffectMode")); } bool isEnable = option->state.testFlag(QStyle::State_Enabled); bool overOrDown = option->state.testFlag(QStyle::State_MouseOver) || option->state.testFlag(QStyle::State_Sunken) || option->state.testFlag(QStyle::State_On) || option->state.testFlag(QStyle::State_Selected); if (auto button = qobject_cast(widget)) { if (button->isDown() || button->isChecked()) { overOrDown = true; } } if (qobject_cast(widget)) { if (!option->state.testFlag(QStyle::State_Selected)) overOrDown = false; } if (isEnable && overOrDown) { QPixmap target = pixmap; if (fillIconSymbolicColor) { target = filledSymbolicColoredPixmap(pixmap, option->palette.highlightedText().color()); } if (!isPurePixmap) return target; QPainter p(&target); p.setRenderHint(QPainter::Antialiasing); p.setRenderHint(QPainter::SmoothPixmapTransform); p.setCompositionMode(QPainter::CompositionMode_SourceIn); p.fillRect(target.rect(), option->palette.highlightedText()); //p.end(); return target; } else { if (mode == BothDefaultAndHighlit) { QPixmap target = pixmap; if (fillIconSymbolicColor) { target = filledSymbolicColoredPixmap(pixmap, option->palette.highlightedText().color()); } if (!isPurePixmap) return target; QPainter p(&target); p.setRenderHint(QPainter::Antialiasing); p.setRenderHint(QPainter::SmoothPixmapTransform); p.setCompositionMode(QPainter::CompositionMode_SourceIn); p.fillRect(target.rect(), option->palette.dark()); //p.end(); return target; } } } } else { if (!isPurePixmap) return pixmap; bool isEnable = option->state.testFlag(QStyle::State_Enabled); bool overOrDown = option->state.testFlag(QStyle::State_MouseOver) || option->state.testFlag(QStyle::State_Sunken) || option->state.testFlag(QStyle::State_Selected) || option->state.testFlag(QStyle::State_On); if (isEnable && overOrDown) { QPixmap target = pixmap; QPainter p(&target); p.setRenderHint(QPainter::Antialiasing); p.setRenderHint(QPainter::SmoothPixmapTransform); p.setCompositionMode(QPainter::CompositionMode_SourceIn); p.fillRect(target.rect(), option->palette.highlightedText()); //p.end(); return target; } else { if (mode == BothDefaultAndHighlit) { QPixmap target = pixmap; QPainter p(&target); p.setRenderHint(QPainter::Antialiasing); p.setRenderHint(QPainter::SmoothPixmapTransform); p.setCompositionMode(QPainter::CompositionMode_SourceIn); p.fillRect(target.rect(), option->palette.dark()); //p.end(); return target; } } } return pixmap; } HighLightEffect::HighLightEffect(QObject *parent) : QObject(parent) { } QPixmap HighLightEffect::filledSymbolicColoredPixmap(const QPixmap &source, const QColor &baseColor) { QImage img = source.toImage(); for (int x = 0; x < img.width(); x++) { for (int y = 0; y < img.height(); y++) { auto color = img.pixelColor(x, y); if (color.alpha() > 0) { int hue = color.hue(); if (!qAbs(hue - symbolic_color.hue()) < 10) { color.setRed(baseColor.red()); color.setGreen(baseColor.green()); color.setBlue(baseColor.blue()); img.setPixelColor(x, y, color); } } } } return QPixmap::fromImage(img); } QPixmap HighLightEffect::drawSymbolicColoredPixmap(const QPixmap &source) { QColor currentcolor=HighLightEffect::getCurrentSymbolicColor(); QColor gray(128,128,128); QColor standard (31,32,34); QImage img = source.toImage(); for (int x = 0; x < img.width(); x++) { for (int y = 0; y < img.height(); y++) { auto color = img.pixelColor(x, y); if (color.alpha() > 0) { if (qAbs(color.red()-gray.red())<20 && qAbs(color.green()-gray.green())<20 && qAbs(color.blue()-gray.blue())<20) { color.setRed(255); color.setGreen(255); color.setBlue(255); img.setPixelColor(x, y, color); } else if(qAbs(color.red()-standard.red())<20 && qAbs(color.green()-standard.green())<20 && qAbs(color.blue()-standard.blue())<20) { color.setRed(255); color.setGreen(255); color.setBlue(255); img.setPixelColor(x, y, color); } else { img.setPixelColor(x, y, color); } } } } return QPixmap::fromImage(img); } QIcon HighLightEffect::drawSymbolicColoredIcon(const QIcon &source) { QColor currentcolor=HighLightEffect::getCurrentSymbolicColor(); QColor gray(128,128,128); QColor standard (31,32,34); QImage img = source.pixmap(32,32).toImage(); for (int x = 0; x < img.width(); x++) { for (int y = 0; y < img.height(); y++) { auto color = img.pixelColor(x, y); if (color.alpha() > 0) { if (qAbs(color.red()-gray.red())<20 && qAbs(color.green()-gray.green())<20 && qAbs(color.blue()-gray.blue())<20) { color.setRed(255); color.setGreen(255); color.setBlue(255); img.setPixelColor(x, y, color); } else if(qAbs(color.red()-standard.red())<20 && qAbs(color.green()-standard.green())<20 && qAbs(color.blue()-standard.blue())<20) { color.setRed(255); color.setGreen(255); color.setBlue(255); img.setPixelColor(x, y, color); } else { img.setPixelColor(x, y, color); } } } } return QPixmap::fromImage(img); } ukui-panel-3.0.6.4/panel/ukuipanelpluginconfigdialog.cpp0000644000175000017500000000477414203402514021750 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2011 Razor team * Authors: * Alexander Sokoloff * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "ukuipanelpluginconfigdialog.h" #include #include #include #include /************************************************ ************************************************/ UKUIPanelPluginConfigDialog::UKUIPanelPluginConfigDialog(PluginSettings &settings, QWidget *parent) : QDialog(parent), mSettings(settings) { } /************************************************ ************************************************/ UKUIPanelPluginConfigDialog::~UKUIPanelPluginConfigDialog() { } /************************************************ ************************************************/ PluginSettings& UKUIPanelPluginConfigDialog::settings() const { return mSettings; } /************************************************ ************************************************/ void UKUIPanelPluginConfigDialog::dialogButtonsAction(QAbstractButton *btn) { QDialogButtonBox *box = qobject_cast(btn->parent()); if (box && box->buttonRole(btn) == QDialogButtonBox::ResetRole) { mSettings.loadFromCache(); loadSettings(); } else { close(); } } /************************************************ ************************************************/ void UKUIPanelPluginConfigDialog::setComboboxIndexByData(QComboBox *comboBox, const QVariant &data, int defaultIndex) const { int index = comboBox ->findData(data); if (index < 0) index = defaultIndex; comboBox->setCurrentIndex(index); } ukui-panel-3.0.6.4/panel/plugin.cpp0000644000175000017500000004423614203402514015461 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2011 Razor team * Authors: * Alexander Sokoloff * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "plugin.h" #include "iukuipanelplugin.h" #include "pluginsettings_p.h" #include "ukuipanel.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //#include #include "common/ukuisettings.h" //#include #include "../panel/common/ukuitranslator.h" #include // statically linked built-in plugins #if defined(WITH_DESKTOPSWITCH_PLUGIN) #include "../plugin-desktopswitch/desktopswitch.h" // desktopswitch extern void * loadPluginTranslation_desktopswitch_helper; #endif #if defined(WITH_MAINMENU_PLUGIN) #include "../plugin-mainmenu/ukuimainmenu.h" // mainmenu extern void * loadPluginTranslation_mainmenu_helper; #endif #if defined(WITH_QUICKLAUNCH_PLUGIN) #include "../plugin-quicklaunch/ukuiquicklaunchplugin.h" // quicklaunch extern void * loadPluginTranslation_quicklaunch_helper; #endif #if defined(WITH_SHOWDESKTOP_PLUGIN) #include "../plugin-showdesktop/showdesktop.h" // showdesktop extern void * loadPluginTranslation_showdesktop_helper; #endif #if defined(WITH_SPACERX_PLUGIN) #include "../plugin-spacerx/spacerx.h" // spacerx extern void * loadPluginTranslation_spacerx_helper; #endif #if defined(WITH_SPACER_PLUGIN) #include "../plugin-spacer/spacer.h" // spacer extern void * loadPluginTranslation_spacer_helper; #endif #if defined(WITH_STATUSNOTIFIER_PLUGIN) #include "../plugin-statusnotifier/statusnotifier.h" // statusnotifier extern void * loadPluginTranslation_statusnotifier_helper; #endif #if defined(WITH_TASKBAR_PLUGIN) #include "../plugin-taskbar/ukuitaskbarplugin.h" // taskbar extern void * loadPluginTranslation_taskbar_helper; #endif #if defined(WITH_TRAY_PLUGIN) #include "../plugin-tray/ukuitrayplugin.h" // tray extern void * loadPluginTranslation_tray_helper; #endif #if defined(WITH_QUICKLAUNCH_PLUGIN) #include "../plugin-statusnotifier/statusnotifier.h" // statusnotifier extern void * loadPluginTranslation_quicklaunch_helper; #endif #if defined(WITH_WORLDCLOCK_PLUGIN) #include "../plugin-worldclock/ukuiworldclock.h" // worldclock extern void * loadPluginTranslation_worldclock_helper; #endif #if defined(WITH_CALENDAR_PLUGIN) #include "../plugin-calendar/ukuicalendar.h" // indicatorCalendar extern void * loadPluginTranslation_calendar_helper; #endif #if defined(WITH_STARTMENU_PLUGIN) #include "../plugin-startmenu/startmenu.h" // startmenu extern void * loadPluginTranslation_startmenu_helper; #endif #if defined(WITH_SEGMENTATION_PLUGIN) #include "../plugin-segmentation/segmentation.h" // startmenu extern void * loadPluginTranslation_segmentation_helper; #endif #if defined(WITH_NIGHTMODE_PLUGIN) #include "../plugin-nightmode/nightmode.h" // startmenu extern void * loadPluginTranslation_nightmode_helper; #endif QColor Plugin::mMoveMarkerColor= QColor(255, 0, 0, 255); /************************************************ ************************************************/ Plugin::Plugin(const UKUi::PluginInfo &desktopFile, UKUi::Settings *settings, const QString &settingsGroup,UKUIPanel *panel) : QFrame(panel), mDesktopFile(desktopFile), mPluginLoader(0), mPlugin(0), mPluginWidget(0), mAlignment(AlignLeft), mPanel(panel) { mSettings = PluginSettingsFactory::create(settings, settingsGroup); setWindowTitle(desktopFile.name()); mName = desktopFile.name(); QStringList dirs; dirs << QProcessEnvironment::systemEnvironment().value("UKUIPanel_PLUGIN_PATH").split(":"); dirs << PLUGIN_DIR; bool found = false; if(IUKUIPanelPluginLibrary const * pluginLib = findStaticPlugin(desktopFile.id())) { // this is a static plugin found = true; loadLib(pluginLib); } else { // this plugin is a dynamically loadable module QString baseName = QString("lib%1.so").arg(desktopFile.id()); #if (QT_VERSION < QT_VERSION_CHECK(5,7,0)) for(int i=0;i= QT_VERSION_CHECK(5,7,0)) for(const QString &dirName : qAsConst(dirs)){ #endif QFileInfo fi(QDir(dirName), baseName); if (fi.exists()) { found = true; if (loadModule(fi.absoluteFilePath())) break; } } } if (!isLoaded()) { if (!found) qWarning() << QString("Plugin %1 not found in the").arg(desktopFile.id()) << dirs; return; } setObjectName(mPlugin->themeId() + "Plugin"); // plugin handle for easy context menu setProperty("NeedsHandle", mPlugin->flags().testFlag(IUKUIPanelPlugin::NeedsHandle)); QString s = mSettings->value("alignment").toString(); // Retrun default value if (s.isEmpty()) { mAlignment = (mPlugin->flags().testFlag(IUKUIPanelPlugin::PreferRightAlignment)) ? Plugin::AlignRight : Plugin::AlignLeft; } else { mAlignment = (s.toUpper() == "RIGHT") ? Plugin::AlignRight : Plugin::AlignLeft; } if (mPluginWidget) { QGridLayout* layout = new QGridLayout(this); layout->setSpacing(0); layout->setContentsMargins(0, 0, 0, 0); setLayout(layout); layout->addWidget(mPluginWidget, 0, 0); } saveSettings(); // delay the connection to settingsChanged to avoid conflicts // while the plugin is still being initialized connect(mSettings, &PluginSettings::settingsChanged, this, &Plugin::settingsChanged); } /************************************************ ************************************************/ Plugin::~Plugin() { delete mPlugin; delete mPluginLoader; delete mSettings; } void Plugin::setAlignment(Plugin::Alignment alignment) { mAlignment = alignment; saveSettings(); } /************************************************ ************************************************/ namespace { //helper types for static plugins storage & binary search typedef std::unique_ptr plugin_ptr_t; typedef std::tuple plugin_tuple_t; //NOTE: Please keep the plugins sorted by name while adding new plugins. //NOTE2: we need to reference some (dummy) symbol from (autogenerated) UKUiPluginTranslationLoader.cpp // to be not stripped (as unused/unreferenced) in static linking time static plugin_tuple_t const static_plugins[] = { #if defined(WITH_CALENDAR_PLUGIN) std::make_tuple(QLatin1String("calendar"), plugin_ptr_t{new IndicatorCalendarPluginLibrary}, loadPluginTranslation_calendar_helper),// desktopswitch #endif #if defined(WITH_DESKTOPSWITCH_PLUGIN) std::make_tuple(QLatin1String("desktopswitch"), plugin_ptr_t{new DesktopSwitchPluginLibrary}, loadPluginTranslation_desktopswitch_helper),// desktopswitch #endif #if defined(WITH_MAINMENU_PLUGIN) std::make_tuple(QLatin1String("mainmenu"), plugin_ptr_t{new UKUiMainMenuPluginLibrary}, loadPluginTranslation_mainmenu_helper),// mainmenu #endif #if defined(WITH_QUICKLAUNCH_PLUGIN) std::make_tuple(QLatin1String("quicklaunch"), plugin_ptr_t{new UKUIQuickLaunchPluginLibrary}, loadPluginTranslation_quicklaunch_helper),// quicklaunch #endif #if defined(WITH_SHOWDESKTOP_PLUGIN) std::make_tuple(QLatin1String("showdesktop"), plugin_ptr_t{new ShowDesktopLibrary}, loadPluginTranslation_showdesktop_helper),// showdesktop #endif #if defined(WITH_SPACERX_PLUGIN) std::make_tuple(QLatin1String("spacerx"), plugin_ptr_t{new SpacerXPluginLibrary}, loadPluginTranslation_spacerx_helper),// spacerx #endif #if defined(WITH_SPACER_PLUGIN) std::make_tuple(QLatin1String("spacer"), plugin_ptr_t{new SpacerPluginLibrary}, loadPluginTranslation_spacer_helper),// spacer #endif #if defined(WITH_STATUSNOTIFIER_PLUGIN) std::make_tuple(QLatin1String("statusnotifier"), plugin_ptr_t{new StatusNotifierLibrary}, loadPluginTranslation_statusnotifier_helper),// statusnotifier #endif #if defined(WITH_TASKBAR_PLUGIN) std::make_tuple(QLatin1String("taskbar"), plugin_ptr_t{new UKUITaskBarPluginLibrary}, loadPluginTranslation_taskbar_helper),// taskbar #endif #if defined(WITH_TRAY_PLUGIN) std::make_tuple(QLatin1String("tray"), plugin_ptr_t{new UKUITrayPluginLibrary}, loadPluginTranslation_tray_helper),// tray #endif #if defined(WITH_WORLDCLOCK_PLUGIN) std::make_tuple(QLatin1String("worldclock"), plugin_ptr_t{new UKUiWorldClockLibrary}, loadPluginTranslation_worldclock_helper),// worldclock #endif #if defined(WITH_CALENDAR_PLUGIN) std::make_tuple(QLatin1String("calendar"), plugin_ptr_t{new UKUICalendarPluginLibrary}, loadPluginTranslation_calendar_helper),// calendar #endif #if defined(WITH_STARTMENU_PLUGIN) std::make_tuple(QLatin1String("startmenu"), plugin_ptr_t{new UKUIStartMenuLibrary}, loadPluginTranslation_startmenu_helper),// startmenu #endif #if defined(WITH_SEGMENTATION_PLUGIN) std::make_tuple(QLatin1String("segmentation"), plugin_ptr_t{new StartMenuLibrary}, loadPluginTranslation_segementation_helper),// startmenu #endif #if defined(WITH_NIGHTMODE_PLUGIN) std::make_tuple(QLatin1String("nightmode"), plugin_ptr_t{new NightModeLibrary}, loadPluginTranslation_nightmode_helper),// nightmode #endif }; static constexpr plugin_tuple_t const * const plugins_begin = static_plugins; static constexpr plugin_tuple_t const * const plugins_end = static_plugins + sizeof (static_plugins) / sizeof (static_plugins[0]); struct assert_helper { assert_helper() { Q_ASSERT(std::is_sorted(plugins_begin, plugins_end , [] (plugin_tuple_t const & p1, plugin_tuple_t const & p2) -> bool { return std::get<0>(p1) < std::get<0>(p2); })); } }; static assert_helper h; } IUKUIPanelPluginLibrary const * Plugin::findStaticPlugin(const QString &libraryName) { // find a static plugin library by name -> binary search plugin_tuple_t const * plugin = std::lower_bound(plugins_begin, plugins_end, libraryName , [] (plugin_tuple_t const & plugin, QString const & name) -> bool { return std::get<0>(plugin) < name; }); if (plugins_end != plugin && libraryName == std::get<0>(*plugin)) return std::get<1>(*plugin).get(); return nullptr; } // load a plugin from a library bool Plugin::loadLib(IUKUIPanelPluginLibrary const * pluginLib) { IUKUIPanelPluginStartupInfo startupInfo; startupInfo.settings = mSettings; startupInfo.desktopFile = &mDesktopFile; startupInfo.ukuiPanel = mPanel; mPlugin = pluginLib->instance(startupInfo); if (!mPlugin) { qWarning() << QString("Can't load plugin \"%1\". Plugin can't build IUKUIPanelPlugin.").arg(mDesktopFile.id()); return false; } mPluginWidget = mPlugin->widget(); if (mPluginWidget) { mPluginWidget->setObjectName(mPlugin->themeId()); watchWidgets(mPluginWidget); } this->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); return true; } // load dynamic plugin from a *.so module bool Plugin::loadModule(const QString &libraryName) { mPluginLoader = new QPluginLoader(libraryName); if (!mPluginLoader->load()) { qWarning() << mPluginLoader->errorString(); return false; } QObject *obj = mPluginLoader->instance(); if (!obj) { qWarning() << mPluginLoader->errorString(); return false; } IUKUIPanelPluginLibrary* pluginLib= qobject_cast(obj); if (!pluginLib) { qWarning() << QString("Can't load plugin \"%1\". Plugin is not a IUKUIPanelPluginLibrary.").arg(mPluginLoader->fileName()); delete obj; return false; } return loadLib(pluginLib); } /************************************************ ************************************************/ void Plugin::watchWidgets(QObject * const widget) { // the QWidget might not be fully constructed yet, but we can rely on the isWidgetType() if (!widget->isWidgetType()) return; widget->installEventFilter(this); // watch also children (recursive) for (auto const & child : widget->children()) { watchWidgets(child); } } /************************************************ ************************************************/ void Plugin::unwatchWidgets(QObject * const widget) { widget->removeEventFilter(this); // unwatch also children (recursive) for (auto const & child : widget->children()) { unwatchWidgets(child); } } /************************************************ ************************************************/ void Plugin::settingsChanged() { mPlugin->settingsChanged(); } /************************************************ ************************************************/ void Plugin::saveSettings() { mSettings->setValue("alignment", (mAlignment == AlignLeft) ? "Left" : "Right"); mSettings->setValue("type", mDesktopFile.id()); mSettings->sync(); } /************************************************ ************************************************/ void Plugin::contextMenuEvent(QContextMenuEvent *event) { mPanel->showPopupMenu(this); } /************************************************ ************************************************/ void Plugin::mousePressEvent(QMouseEvent *event) { switch (event->button()) { case Qt::LeftButton: mPlugin->activated(IUKUIPanelPlugin::Trigger); break; case Qt::MidButton: mPlugin->activated(IUKUIPanelPlugin::MiddleClick); break; default: break; } } /************************************************ ************************************************/ void Plugin::mouseDoubleClickEvent(QMouseEvent*) { mPlugin->activated(IUKUIPanelPlugin::DoubleClick); } /************************************************ ************************************************/ void Plugin::showEvent(QShowEvent *) { if (mPluginWidget) mPluginWidget->adjustSize(); } /************************************************ ************************************************/ QMenu *Plugin::popupMenu() const { QString name = this->name().replace("&", "&&"); QMenu* menu = new QMenu(windowTitle()); /* //set top menu selection ,do not delete until you get the ui finish if (mPlugin->flags().testFlag(IUKUIPanelPlugin::HaveConfigDialog)) { QAction* configAction = new QAction( XdgIcon::fromTheme(QLatin1String("preferences-other")), tr("Configure \"%1\"").arg(name), menu); menu->addAction(configAction); connect(configAction, SIGNAL(triggered()), this, SLOT(showConfigureDialog())); } QAction* moveAction = new QAction(XdgIcon::fromTheme("transform-move"), tr("Move \"%1\"").arg(name), menu); menu->addAction(moveAction); connect(moveAction, SIGNAL(triggered()), this, SIGNAL(startMove())); menu->addSeparator(); QAction* removeAction = new QAction( XdgIcon::fromTheme(QLatin1String("list-remove")), tr("Remove \"%1\"").arg(name), menu); menu->addAction(removeAction); connect(removeAction, SIGNAL(triggered()), this, SLOT(requestRemove())); */ return menu; } /************************************************ ************************************************/ bool Plugin::isSeparate() const { return mPlugin->isSeparate(); } /************************************************ ************************************************/ bool Plugin::isExpandable() const { return mPlugin->isExpandable(); } /************************************************ ************************************************/ bool Plugin::eventFilter(QObject * watched, QEvent * event) { switch (event->type()) { case QEvent::DragLeave: emit dragLeft(); break; case QEvent::ChildAdded: watchWidgets(dynamic_cast(event)->child()); break; case QEvent::ChildRemoved: unwatchWidgets(dynamic_cast(event)->child()); break; default: break; } return false; } /************************************************ ************************************************/ void Plugin::realign() { if (mPlugin) mPlugin->realign(); } /************************************************ ************************************************/ void Plugin::showConfigureDialog() { if (!mConfigDialog) mConfigDialog = mPlugin->configureDialog(); if (!mConfigDialog) return; connect(this, &Plugin::destroyed, mConfigDialog.data(), &QWidget::close); mPanel->willShowWindow(mConfigDialog); mConfigDialog->show(); mConfigDialog->raise(); mConfigDialog->activateWindow(); WId wid = mConfigDialog->windowHandle()->winId(); KWindowSystem::activateWindow(wid); KWindowSystem::setOnDesktop(wid, KWindowSystem::currentDesktop()); } /************************************************ ************************************************/ void Plugin::requestRemove() { emit remove(); deleteLater(); } ukui-panel-3.0.6.4/panel/ukuicontrolstyle.h0000644000175000017500000000252714203402514017264 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include class UKUiMenu:public QMenu { public: UKUiMenu(); ~UKUiMenu(); protected: void paintEvent(QPaintEvent*); }; class UkuiToolButton:public QToolButton { public: UkuiToolButton(); ~UkuiToolButton(); void paintTooltipStyle(); }; class UKUiFrame:public QFrame { public: UKUiFrame(); ~UKUiFrame(); protected: void paintEvent(QPaintEvent*); }; class UKUiWidget:public QWidget { public: UKUiWidget(); ~UKUiWidget(); protected: void paintEvent(QPaintEvent*); }; #endif ukui-panel-3.0.6.4/panel/ukuipanellayout.cpp0000644000175000017500000007111114203402514017406 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2011 Razor team * Authors: * Alexander Sokoloff * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "ukuipanellayout.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "plugin.h" #include "ukuipanellimits.h" #include "iukuipanelplugin.h" #include "ukuipanel.h" #include "pluginmoveprocessor.h" #include #include #define ANIMATION_DURATION 250 class ItemMoveAnimation : public QVariantAnimation { public: ItemMoveAnimation(QLayoutItem *item) : mItem(item) { setEasingCurve(QEasingCurve::OutBack); setDuration(ANIMATION_DURATION); } void updateCurrentValue(const QVariant ¤t) { mItem->setGeometry(current.toRect()); } private: QLayoutItem* mItem; }; struct LayoutItemInfo { LayoutItemInfo(QLayoutItem *layoutItem=0); QLayoutItem *item; QRect geometry; bool separate; bool expandable; }; LayoutItemInfo::LayoutItemInfo(QLayoutItem *layoutItem): item(layoutItem), separate(false), expandable(false) { if (!item) return; Plugin *p = qobject_cast(item->widget()); if (p) { separate = p->isSeparate(); expandable = p->isExpandable(); return; } } /************************************************ This is logical plugins grid, it's same for horizontal and vertical panel. Plugins keeps as: <---LineCount--> + ---+----+----+ | P1 | P2 | P3 | +----+----+----+ | P4 | P5 | | +----+----+----+ ... +----+----+----+ | PN | | | +----+----+----+ ************************************************/ class LayoutItemGrid { public: explicit LayoutItemGrid(); ~LayoutItemGrid(); void addItem(QLayoutItem *item); int count() const { return mItems.count(); } QLayoutItem *itemAt(int index) const { return mItems[index]; } QLayoutItem *takeAt(int index); const LayoutItemInfo &itemInfo(int row, int col) const; LayoutItemInfo &itemInfo(int row, int col); void update(); int lineSize() const { return mLineSize; } void setLineSize(int value); int colCount() const { return mColCount; } void setColCount(int value); int usedColCount() const { return mUsedColCount; } int rowCount() const { return mRowCount; } void invalidate() { mValid = false; } bool isValid() const { return mValid; } QSize sizeHint() const { return mSizeHint; } bool horiz() const { return mHoriz; } void setHoriz(bool value); void clear(); void rebuild(); bool isExpandable() const { return mExpandable; } int expandableSize() const { return mExpandableSize; } void moveItem(int from, int to); private: QVector mInfoItems; int mColCount; int mUsedColCount; int mRowCount; bool mValid; int mExpandableSize; int mLineSize; QSize mSizeHint; QSize mMinSize; bool mHoriz; int mNextRow; int mNextCol; bool mExpandable; QList mItems; void doAddToGrid(QLayoutItem *item); }; /************************************************ ************************************************/ LayoutItemGrid::LayoutItemGrid() { mLineSize = 0; mHoriz = true; clear(); } LayoutItemGrid::~LayoutItemGrid() { qDeleteAll(mItems); } /************************************************ ************************************************/ void LayoutItemGrid::clear() { mRowCount = 0; mNextRow = 0; mNextCol = 0; mInfoItems.resize(0); mValid = false; mExpandable = false; mExpandableSize = 0; mUsedColCount = 0; mSizeHint = QSize(0,0); mMinSize = QSize(0,0); } /************************************************ ************************************************/ void LayoutItemGrid::rebuild() { clear(); #if (QT_VERSION < QT_VERSION_CHECK(5,7,0)) for(int i=0;i= QT_VERSION_CHECK(5,7,0)) for(QLayoutItem *item : qAsConst(mItems)){ #endif doAddToGrid(item); } } /************************************************ ************************************************/ void LayoutItemGrid::addItem(QLayoutItem *item) { doAddToGrid(item); mItems.append(item); } /************************************************ ************************************************/ void LayoutItemGrid::doAddToGrid(QLayoutItem *item) { LayoutItemInfo info(item); if (info.separate && mNextCol > 0) { mNextCol = 0; mNextRow++; } int cnt = (mNextRow + 1 ) * mColCount; if (mInfoItems.count() <= cnt) mInfoItems.resize(cnt); int idx = mNextRow * mColCount + mNextCol; mInfoItems[idx] = info; mUsedColCount = qMax(mUsedColCount, mNextCol + 1); mExpandable = mExpandable || info.expandable; mRowCount = qMax(mRowCount, mNextRow+1); if (info.separate || mNextCol >= mColCount-1) { mNextRow++; mNextCol = 0; } else { mNextCol++; } invalidate(); } /************************************************ ************************************************/ QLayoutItem *LayoutItemGrid::takeAt(int index) { QLayoutItem *item = mItems.takeAt(index); rebuild(); return item; } /************************************************ ************************************************/ void LayoutItemGrid::moveItem(int from, int to) { mItems.move(from, to); rebuild(); } /************************************************ ************************************************/ const LayoutItemInfo &LayoutItemGrid::itemInfo(int row, int col) const { return mInfoItems[row * mColCount + col]; } /************************************************ ************************************************/ LayoutItemInfo &LayoutItemGrid::itemInfo(int row, int col) { return mInfoItems[row * mColCount + col]; } /************************************************ ************************************************/ void LayoutItemGrid::update() { mExpandableSize = 0; mSizeHint = QSize(0,0); if (mHoriz) { mSizeHint.setHeight(mLineSize * mColCount); int x = 0; for (int r=0; rsizeHint(); info.geometry = QRect(QPoint(x,y), sz); y += sz.height(); rw = qMax(rw, sz.width()); } x += rw; if (itemInfo(r, 0).expandable) mExpandableSize += rw; mSizeHint.setWidth(x); mSizeHint.rheight() = qMax(mSizeHint.rheight(), y); } } else { mSizeHint.setWidth(mLineSize * mColCount); int y = 0; for (int r=0; rsizeHint(); info.geometry = QRect(QPoint(x,y), sz); x += sz.width(); rh = qMax(rh, sz.height()); } y += rh; if (itemInfo(r, 0).expandable) mExpandableSize += rh; mSizeHint.setHeight(y); mSizeHint.rwidth() = qMax(mSizeHint.rwidth(), x); } } mValid = true; } /************************************************ ************************************************/ void LayoutItemGrid::setLineSize(int value) { mLineSize = qMax(1, value); invalidate(); } /************************************************ ************************************************/ void LayoutItemGrid::setColCount(int value) { mColCount = qMax(1, value); rebuild(); } /************************************************ ************************************************/ void LayoutItemGrid::setHoriz(bool value) { mHoriz = value; invalidate(); } /************************************************ ************************************************/ UKUIPanelLayout::UKUIPanelLayout(QWidget *parent) : QLayout(parent), mLeftGrid(new LayoutItemGrid()), mRightGrid(new LayoutItemGrid()), mPosition(IUKUIPanel::PositionBottom), mAnimate(false) { setContentsMargins(0, 0, 0, 0); } /************************************************ ************************************************/ UKUIPanelLayout::~UKUIPanelLayout() { delete mLeftGrid; delete mRightGrid; } /************************************************ ************************************************/ void UKUIPanelLayout::addItem(QLayoutItem *item) { LayoutItemGrid *grid = mRightGrid; Plugin *p = qobject_cast(item->widget()); if (p && p->alignment() == Plugin::AlignLeft) grid = mLeftGrid; grid->addItem(item); } /************************************************ ************************************************/ void UKUIPanelLayout::globalIndexToLocal(int index, LayoutItemGrid **grid, int *gridIndex) { if (index < mLeftGrid->count()) { *grid = mLeftGrid; *gridIndex = index; return; } *grid = mRightGrid; *gridIndex = index - mLeftGrid->count(); } /************************************************ ************************************************/ void UKUIPanelLayout::globalIndexToLocal(int index, LayoutItemGrid **grid, int *gridIndex) const { if (index < mLeftGrid->count()) { *grid = mLeftGrid; *gridIndex = index; return; } *grid = mRightGrid; *gridIndex = index - mLeftGrid->count(); } /************************************************ ************************************************/ QLayoutItem *UKUIPanelLayout::itemAt(int index) const { if (index < 0 || index >= count()) return 0; LayoutItemGrid *grid=0; int idx=0; globalIndexToLocal(index, &grid, &idx); return grid->itemAt(idx); } /************************************************ ************************************************/ QLayoutItem *UKUIPanelLayout::takeAt(int index) { if (index < 0 || index >= count()) return 0; LayoutItemGrid *grid=0; int idx=0; globalIndexToLocal(index, &grid, &idx); return grid->takeAt(idx); } /************************************************ ************************************************/ int UKUIPanelLayout::count() const { return mLeftGrid->count() + mRightGrid->count(); } /************************************************ ************************************************/ void UKUIPanelLayout::moveItem(int from, int to, bool withAnimation) { if (from != to) { LayoutItemGrid *fromGrid=0; int fromIdx=0; globalIndexToLocal(from, &fromGrid, &fromIdx); LayoutItemGrid *toGrid=0; int toIdx=0; globalIndexToLocal(to, &toGrid, &toIdx); if (fromGrid == toGrid) { fromGrid->moveItem(fromIdx, toIdx); } else { QLayoutItem *item = fromGrid->takeAt(fromIdx); toGrid->addItem(item); //recalculate position because we removed from one and put to another grid LayoutItemGrid *toGridAux=0; globalIndexToLocal(to, &toGridAux, &toIdx); Q_ASSERT(toGrid == toGridAux); //grid must be the same (if not something is wrong with our logic) toGrid->moveItem(toGridAux->count()-1, toIdx); } } mAnimate = withAnimation; invalidate(); } /************************************************ ************************************************/ QSize UKUIPanelLayout::sizeHint() const { if (!mLeftGrid->isValid()) mLeftGrid->update(); if (!mRightGrid->isValid()) mRightGrid->update(); QSize ls = mLeftGrid->sizeHint(); QSize rs = mRightGrid->sizeHint(); if (isHorizontal()) { return QSize(ls.width() + rs.width(), qMax(ls.height(), rs.height())); } else { return QSize(qMax(ls.width(), rs.width()), ls.height() + rs.height()); } } /************************************************ ************************************************/ void UKUIPanelLayout::setGeometry(const QRect &geometry) { if (!mLeftGrid->isValid()) mLeftGrid->update(); if (!mRightGrid->isValid()) mRightGrid->update(); QRect my_geometry{geometry}; my_geometry -= contentsMargins(); if (count()) { if (isHorizontal()) setGeometryHoriz(my_geometry); else setGeometryVert(my_geometry); } mAnimate = false; QLayout::setGeometry(my_geometry); } /************************************************ ************************************************/ void UKUIPanelLayout::setItemGeometry(QLayoutItem *item, const QRect &geometry, bool withAnimation) { Plugin *plugin = qobject_cast(item->widget()); if (withAnimation && plugin) { ItemMoveAnimation* animation = new ItemMoveAnimation(item); animation->setStartValue(item->geometry()); animation->setEndValue(geometry); animation->start(animation->DeleteWhenStopped); animation->deleteLater(); } else { item->setGeometry(geometry); } } /************************************************ ************************************************/ void UKUIPanelLayout::setGeometryHoriz(const QRect &geometry) { const bool visual_h_reversed = parentWidget() && parentWidget()->isRightToLeft(); // Calc expFactor for expandable plugins like TaskBar. double expFactor; { int expWidth = mLeftGrid->expandableSize() + mRightGrid->expandableSize(); int nonExpWidth = mLeftGrid->sizeHint().width() - mLeftGrid->expandableSize() + mRightGrid->sizeHint().width() - mRightGrid->expandableSize(); expFactor = expWidth ? ((1.0 * geometry.width() - nonExpWidth) / expWidth) : 1; } // Calc baselines for plugins like button. QVector baseLines(qMax(mLeftGrid->colCount(), mRightGrid->colCount())); const int bh = geometry.height() / baseLines.count(); const int base_center = bh >> 1; const int height_remain = 0 < bh ? geometry.height() % baseLines.size() : 0; { int base = geometry.top(); for (auto i = baseLines.begin(), i_e = baseLines.end(); i_e != i; ++i, base += bh) { *i = base; } } #if 0 qDebug() << "** UKUIPanelLayout::setGeometryHoriz **************"; qDebug() << "geometry: " << geometry; qDebug() << "Left grid"; qDebug() << " cols:" << mLeftGrid->colCount() << " rows:" << mLeftGrid->rowCount(); qDebug() << " usedCols" << mLeftGrid->usedColCount(); qDebug() << "Right grid"; qDebug() << " cols:" << mRightGrid->colCount() << " rows:" << mRightGrid->rowCount(); qDebug() << " usedCols" << mRightGrid->usedColCount(); #endif // Left aligned plugins. int left=geometry.left(); for (int r=0; rrowCount(); ++r) { int rw = 0; int remain = height_remain; for (int c=0; cusedColCount(); ++c) { const LayoutItemInfo &info = mLeftGrid->itemInfo(r, c); if (info.item) { QRect rect; if (info.separate) { rect.setLeft(left); rect.setTop(geometry.top()); rect.setHeight(geometry.height()); if (info.expandable) rect.setWidth(info.geometry.width() * expFactor); else rect.setWidth(info.geometry.width()); } else { int height = bh + (0 < remain-- ? 1 : 0); if (!info.item->expandingDirections().testFlag(Qt::Orientation::Vertical)) height = qMin(info.geometry.height(), height); height = qMin(geometry.height(), height); rect.setHeight(height); rect.setWidth(qMin(info.geometry.width(), geometry.width())); if (height < bh) rect.moveCenter(QPoint(0, baseLines[c] + base_center)); else rect.moveTop(baseLines[c]); rect.moveLeft(left); } rw = qMax(rw, rect.width()); if (visual_h_reversed) rect.moveLeft(geometry.left() + geometry.right() - rect.x() - rect.width() + 1); setItemGeometry(info.item, rect, mAnimate); } } left += rw; } // Right aligned plugins. int right=geometry.right(); for (int r=mRightGrid->rowCount()-1; r>=0; --r) { int rw = 0; int remain = height_remain; for (int c=0; cusedColCount(); ++c) { const LayoutItemInfo &info = mRightGrid->itemInfo(r, c); if (info.item) { QRect rect; if (info.separate) { rect.setTop(geometry.top()); rect.setHeight(geometry.height()); if (info.expandable) rect.setWidth(info.geometry.width() * expFactor); else rect.setWidth(info.geometry.width()); rect.moveRight(right); } else { int height = bh + (0 < remain-- ? 1 : 0); if (!info.item->expandingDirections().testFlag(Qt::Orientation::Vertical)) height = qMin(info.geometry.height(), height); height = qMin(geometry.height(), height); rect.setHeight(height); rect.setWidth(qMin(info.geometry.width(), geometry.width())); if (height < bh) rect.moveCenter(QPoint(0, baseLines[c] + base_center)); else rect.moveTop(baseLines[c]); rect.moveRight(right); } rw = qMax(rw, rect.width()); if (visual_h_reversed) rect.moveLeft(geometry.left() + geometry.right() - rect.x() - rect.width() + 1); setItemGeometry(info.item, rect, mAnimate); } } right -= rw; } } /************************************************ ************************************************/ void UKUIPanelLayout::setGeometryVert(const QRect &geometry) { const bool visual_h_reversed = parentWidget() && parentWidget()->isRightToLeft(); // Calc expFactor for expandable plugins like TaskBar. double expFactor; { int expHeight = mLeftGrid->expandableSize() + mRightGrid->expandableSize(); int nonExpHeight = mLeftGrid->sizeHint().height() - mLeftGrid->expandableSize() + mRightGrid->sizeHint().height() - mRightGrid->expandableSize(); expFactor = expHeight ? ((1.0 * geometry.height() - nonExpHeight) / expHeight) : 1; } // Calc baselines for plugins like button. QVector baseLines(qMax(mLeftGrid->colCount(), mRightGrid->colCount())); const int bw = geometry.width() / baseLines.count(); const int base_center = bw >> 1; const int width_remain = 0 < bw ? geometry.width() % baseLines.size() : 0; { int base = geometry.left(); for (auto i = baseLines.begin(), i_e = baseLines.end(); i_e != i; ++i, base += bw) { *i = base; } } #if 0 qDebug() << "** UKUIPanelLayout::setGeometryVert **************"; qDebug() << "geometry: " << geometry; qDebug() << "Left grid"; qDebug() << " cols:" << mLeftGrid->colCount() << " rows:" << mLeftGrid->rowCount(); qDebug() << " usedCols" << mLeftGrid->usedColCount(); qDebug() << "Right grid"; qDebug() << " cols:" << mRightGrid->colCount() << " rows:" << mRightGrid->rowCount(); qDebug() << " usedCols" << mRightGrid->usedColCount(); #endif // Top aligned plugins. int top=geometry.top(); for (int r=0; rrowCount(); ++r) { int rh = 0; int remain = width_remain; for (int c=0; cusedColCount(); ++c) { const LayoutItemInfo &info = mLeftGrid->itemInfo(r, c); if (info.item) { QRect rect; if (info.separate) { rect.moveTop(top); rect.setLeft(geometry.left()); rect.setWidth(geometry.width()); if (info.expandable) rect.setHeight(info.geometry.height() * expFactor); else rect.setHeight(info.geometry.height()); } else { rect.setHeight(qMin(info.geometry.height(), geometry.height())); int width = bw + (0 < remain-- ? 1 : 0); if (!info.item->expandingDirections().testFlag(Qt::Orientation::Horizontal)) width = qMin(info.geometry.width(), width); width = qMin(geometry.width(), width); rect.setWidth(width); if (width < bw) rect.moveCenter(QPoint(baseLines[c] + base_center, 0)); else rect.moveLeft(baseLines[c]); rect.moveTop(top); } rh = qMax(rh, rect.height()); if (visual_h_reversed) rect.moveLeft(geometry.left() + geometry.right() - rect.x() - rect.width() + 1); setItemGeometry(info.item, rect, mAnimate); } } top += rh; } // Bottom aligned plugins. int bottom=geometry.bottom(); for (int r=mRightGrid->rowCount()-1; r>=0; --r) { int rh = 0; int remain = width_remain; for (int c=0; cusedColCount(); ++c) { const LayoutItemInfo &info = mRightGrid->itemInfo(r, c); if (info.item) { QRect rect; if (info.separate) { rect.setLeft(geometry.left()); rect.setWidth(geometry.width()); if (info.expandable) rect.setHeight(info.geometry.height() * expFactor); else rect.setHeight(info.geometry.height()); rect.moveBottom(bottom); } else { rect.setHeight(qMin(info.geometry.height(), geometry.height())); int width = bw + (0 < remain-- ? 1 : 0); if (!info.item->expandingDirections().testFlag(Qt::Orientation::Horizontal)) width = qMin(info.geometry.width(), width); width = qMin(geometry.width(), width); rect.setWidth(width); if (width < bw) rect.moveCenter(QPoint(baseLines[c] + base_center, 0)); else rect.moveLeft(baseLines[c]); rect.moveBottom(bottom); } rh = qMax(rh, rect.height()); if (visual_h_reversed) rect.moveLeft(geometry.left() + geometry.right() - rect.x() - rect.width() + 1); setItemGeometry(info.item, rect, mAnimate); } } bottom -= rh; } } /************************************************ ************************************************/ void UKUIPanelLayout::invalidate() { mLeftGrid->invalidate(); mRightGrid->invalidate(); mMinPluginSize = QSize(); QLayout::invalidate(); } /************************************************ ************************************************/ int UKUIPanelLayout::lineCount() const { return mLeftGrid->colCount(); } /************************************************ ************************************************/ void UKUIPanelLayout::setLineCount(int value) { mLeftGrid->setColCount(value); mRightGrid->setColCount(value); invalidate(); } /************************************************ ************************************************/ void UKUIPanelLayout::rebuild() { mLeftGrid->rebuild(); mRightGrid->rebuild(); } /************************************************ ************************************************/ int UKUIPanelLayout::lineSize() const { return mLeftGrid->lineSize(); } /************************************************ ************************************************/ void UKUIPanelLayout::setLineSize(int value) { mLeftGrid->setLineSize(value); mRightGrid->setLineSize(value); invalidate(); } /************************************************ ************************************************/ void UKUIPanelLayout::setPosition(IUKUIPanel::Position value) { mPosition = value; mLeftGrid->setHoriz(isHorizontal()); mRightGrid->setHoriz(isHorizontal()); } /************************************************ ************************************************/ bool UKUIPanelLayout::isHorizontal() const { return mPosition == IUKUIPanel::PositionTop || mPosition == IUKUIPanel::PositionBottom; } /************************************************ ************************************************/ bool UKUIPanelLayout::itemIsSeparate(QLayoutItem *item) { if (!item) return true; Plugin *p = qobject_cast(item->widget()); if (!p) return true; return p->isSeparate(); } /************************************************ ************************************************/ void UKUIPanelLayout::startMovePlugin() { Plugin *plugin = qobject_cast(sender()); if (plugin) { // We have not memoryleaks there. // The processor will be automatically deleted when stopped. PluginMoveProcessor *moveProcessor = new PluginMoveProcessor(this, plugin); moveProcessor->start(); connect(moveProcessor, SIGNAL(finished()), this, SLOT(finishMovePlugin())); } } /************************************************ ************************************************/ void UKUIPanelLayout::finishMovePlugin() { PluginMoveProcessor *moveProcessor = qobject_cast(sender()); if (moveProcessor) { Plugin *plugin = moveProcessor->plugin(); int n = indexOf(plugin); plugin->setAlignment(ncount() ? Plugin::AlignLeft : Plugin::AlignRight); emit pluginMoved(plugin); } } /************************************************ ************************************************/ void UKUIPanelLayout::moveUpPlugin(Plugin * plugin) { const int i = indexOf(plugin); if (0 < i) moveItem(i, i - 1, true); } /************************************************ ************************************************/ void UKUIPanelLayout::addPlugin(Plugin * plugin) { connect(plugin, &Plugin::startMove, this, &UKUIPanelLayout::startMovePlugin); const int prev_count = count(); addWidget(plugin); //check actual position const int pos = indexOf(plugin); if (prev_count > pos) moveItem(pos, prev_count, false); } ukui-panel-3.0.6.4/panel/ukuipanelglobals.h0000644000175000017500000000232514203402514017162 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2013 LXQt team * Authors: * Hong Jen Yee (PCMan) * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef __UKUI_PANEL_GLOBALS_H__ #define __UKUI_PANEL_GLOBALS_H__ #include #ifdef COMPILE_UKUI_PANEL #define UKUI_PANEL_API Q_DECL_EXPORT #else #define UKUI_PANEL_API Q_DECL_IMPORT #endif #endif // __UKUI_PANEL_GLOBALS_H__ ukui-panel-3.0.6.4/panel/windownotifier.h0000644000175000017500000000274514203402514016676 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2015 LXQt team * Authors: * Palo Kisa * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #if !defined(WINDOWNOTIFIER_H) #define WINDOWNOTIFIER_H #include class QWidget; class WindowNotifier : public QObject { Q_OBJECT public: using QObject::QObject; void observeWindow(QWidget * w); inline bool isAnyWindowShown() const { return !mShownWindows.isEmpty(); } virtual bool eventFilter(QObject * watched, QEvent * event) override; signals: void lastHidden(); void firstShown(); private: QList mShownWindows; //!< known shown windows (sorted) }; #endif ukui-panel-3.0.6.4/panel/customstyle.h0000644000175000017500000002015314203402514016213 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA */ #ifndef CUSTOMSTYLE_H #define CUSTOMSTYLE_H #include #include /*! * \brief The CustomStyle class * \details * 自定义QStyle * 基于QProxyStyle,默认使用QProxyStyle的实例绘制控件,你需要针对某一个控件重新实现若干对应的接口。 * QProxyStyle可以从现有的qt style实例化,我们只需要知道这个style的名字即可。 * 这种做法带来了不错的扩展性和自由度,因为我们不需要将某个style的代码直接引入我们的项目中, * 也能够“继承”这个style类进行二次开发。 * * 下面的方法展现了QStyle的所有的接口,使用QStyle进行控件的绘制使得qt应用能够进行风格的切换, * 从而达到不修改项目源码却对应用外观产生巨大影响的效果。 * * \note * 需要注意QStyle与QSS并不兼容,因为QSS本身其实上也是QStyle的一种实现,对一个控件而言,本身理论上只能 * 在同一时间调用唯一一个QStyle进行绘制。 */ class CustomStyle : public QProxyStyle { Q_OBJECT public: //proxyStyleName 是关于样式类型的,&proxyStyleName = "windows" 会造成toolTips的样式为windows类型样式 explicit CustomStyle(const QString &proxyStyleName = "ukui",bool multileWins=false, QObject *parent = nullptr); ~CustomStyle(); /*! * \brief drawComplexControl * \param control 比如ScrollBar,对应CC枚举类型 * \param option * \param painter * \param widget * \details * drawComplexControl用于绘制具有子控件的复杂控件,它本身一般不直接绘制控件, * 而是通过QStyle的其它方法将复杂控件分解成子控件再调用其它的draw方法绘制。 * 如果你需要重新实现一个复杂控件的绘制方法,首先考虑的应该是在不改变它原有的绘制流程的情况下, * 对它调用到的其它方法进行重写。 * * 如果你不想使用原有的绘制流程,那你需要重写这个接口,然后自己实现一切, * 包括背景的绘制,子控件的位置和状态计算,子控件的绘制等。 * 所以,你需要对这个控件有足够的了解之后再尝试直接重写这个接口。 */ virtual void drawComplexControl(QStyle::ComplexControl control, const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget = nullptr) const; /*! * \brief drawControl * \param element 比如按钮,对应CE枚举类型 * \param option * \param painter * \param widget * \details * drawControl用于绘制基本控件元素,它本身一般只负责绘制控件的一部分或者一层。 * 如果你想要知道控件具体如何绘制,你需要同时研究这个控件的源码和QStyle中的源码, * 因为它们都有可能改变控件的绘制流程。 * * QStyle一般会遵循QCommonStyle的绘制流程,QCommenStyle是大部分主流style的最基类, * 它本身不能完全称之为一个主题,如果你直接使用它,你的控件将不能被正常绘制,因为它有可能只是 * 在特定的时候执行了特定却未实现的绘制方法,它更像一个框架或者规范。 */ virtual void drawControl(QStyle::ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget = nullptr) const; virtual void drawItemPixmap(QPainter *painter, const QRect &rectangle, int alignment, const QPixmap &pixmap) const; virtual void drawItemText(QPainter *painter, const QRect &rectangle, int alignment, const QPalette &palette, bool enabled, const QString &text, QPalette::ColorRole textRole = QPalette::NoRole) const; /*! * \brief drawPrimitive * \param element 背景绘制,对应PE枚举类型 * \param option * \param painter * \param widget * \details * drawPrimitive用于绘制控件背景,比如按钮和菜单的背景, * 我们一般需要判断控件的状态来绘制不同的背景, * 比如按钮的hover和点击效果。 */ virtual void drawPrimitive(QStyle::PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget = nullptr) const; virtual QPixmap generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap, const QStyleOption *option) const; virtual QStyle::SubControl hitTestComplexControl(QStyle::ComplexControl control, const QStyleOptionComplex *option, const QPoint &position, const QWidget *widget = nullptr) const; virtual QRect itemPixmapRect(const QRect &rectangle, int alignment, const QPixmap &pixmap) const; virtual QRect itemTextRect(const QFontMetrics &metrics, const QRect &rectangle, int alignment, bool enabled, const QString &text) const; //virtual int layoutSpacing(QSizePolicy::ControlType control1, QSizePolicy::ControlType control2, Qt::Orientation orientation, const QStyleOption *option, const QWidget *widget); virtual int pixelMetric(QStyle::PixelMetric metric, const QStyleOption *option = nullptr, const QWidget *widget = nullptr) const; /*! * \brief polish * \param widget * \details * polish用于对widget进行预处理,一般我们可以在polish中修改其属性, * 另外,polish是对动画和特效实现而言十分重要的一个方法, * 通过polish我们能够使widget和特效和动画形成对应关系。 */ virtual void polish(QWidget *widget); virtual void polish(QApplication *application); virtual void polish(QPalette &palette); virtual void unpolish(QWidget *widget); virtual void unpolish(QApplication *application); virtual QSize sizeFromContents(QStyle::ContentsType type, const QStyleOption *option, const QSize &contentsSize, const QWidget *widget = nullptr) const; virtual QIcon standardIcon(QStyle::StandardPixmap standardIcon, const QStyleOption *option, const QWidget *widget) const; virtual QPalette standardPalette() const; /*! * \brief styleHint * \param hint 对应的枚举是SH * \param option * \param widget * \param returnData * \return * \details * styleHint比较特殊,通过它我们能够改变一些控件的绘制流程或者方式,比如说QMenu是否可以滚动。 */ virtual int styleHint(QStyle::StyleHint hint, const QStyleOption *option = nullptr, const QWidget *widget = nullptr, QStyleHintReturn *returnData = nullptr) const; /*! * \brief subControlRect * \param control * \param option * \param subControl * \param widget * \return * \details * subControlRect返回子控件的位置和大小信息,这个方法一般在内置流程中调用, * 如果我们要重写某个绘制方法,可能需要用到它 */ virtual QRect subControlRect(QStyle::ComplexControl control, const QStyleOptionComplex *option, QStyle::SubControl subControl, const QWidget *widget = nullptr) const; /*! * \brief subElementRect * \param element * \param option * \param widget * \return * \details * 与subControlRect类似 */ virtual QRect subElementRect(QStyle::SubElement element, const QStyleOption *option, const QWidget *widget = nullptr) const; signals: public slots: private: QString pluginName; bool multileWindow = false; }; #endif // CUSTOMSTYLE_H ukui-panel-3.0.6.4/panel/common_fun/0000755000175000017500000000000014203402514015606 5ustar fengfengukui-panel-3.0.6.4/panel/common_fun/ukuipanel_infomation.cpp0000644000175000017500000001623414203402514022540 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #define PANEL_SETTINGS "org.ukui.panel.settings" #define PANEL_POSITION_KEY "panelposition" #define ICON_SIZE_KEY "iconsize" #define PANEL_SIZE_KEY "panelsize" QString panelPositionTransform(int p) { switch (p){ case 1: return "Top"; break; case 2: return "Left"; break; case 3: return "Right"; break; default: return "Bottom"; break; } } UKuiPanelInformation::UKuiPanelInformation(QObject *parent) : QObject(parent) { QDBusConnection::sessionBus().connect(QString(), QString( "/panel/position"), "org.ukui.panel", "UKuiPanelPosition", this, SLOT(setPanelInformation(int,int,int,int,int,int)) ); } void UKuiPanelInformation::setPanelInformation(int x, int y, int width, int height, int size, int position) { screen_x=x; screen_y=y; screen_width=width; screen_height=height; panelsize=size; panelposition=position; QDBusMessage message = QDBusMessage::createSignal("/panel/position", "org.ukui.panel", "PrimaryScreenAvailiableGeometryChanged"); QList args; args.append(screen_x); args.append(screen_y); args.append(screen_width); args.append(screen_height); message.setArguments(args); QDBusConnection::sessionBus().send(message); QDBusMessage message_refresh = QDBusMessage::createSignal("/panel/position", "org.ukui.panel", "PanelGeometryRefresh"); QDBusConnection::sessionBus().send(message_refresh); } QVariantList UKuiPanelInformation::GetPrimaryScreenGeometry() { int available_primary_screen_x;int available_primary_screen_y ; int available_primary_screen_width; int available_primary_screen_height;int available_panel_position; QVariantList vlist; switch(panelposition){ case 0: available_primary_screen_x=screen_x; available_primary_screen_y=screen_y; available_primary_screen_width=screen_width; available_primary_screen_height=screen_height-panelsize; break; case 1: available_primary_screen_x=screen_x; available_primary_screen_y=screen_y+panelsize; available_primary_screen_width=screen_width; available_primary_screen_height=screen_height-panelsize; break; case 2: available_primary_screen_x=screen_x + panelsize; available_primary_screen_y=screen_y; available_primary_screen_width=screen_width-panelsize; available_primary_screen_height=screen_height; break; case 3: available_primary_screen_x=screen_x; available_primary_screen_y=screen_y; available_primary_screen_width=screen_width-panelsize; available_primary_screen_height=screen_height; break; default: available_primary_screen_x=screen_x; available_primary_screen_y=screen_y; available_primary_screen_width=screen_width; available_primary_screen_height=screen_height-panelsize; break; } vlist< #include #include #include class UKuiPanelInformation : public QObject { Q_OBJECT Q_CLASSINFO("D-Bus Interface","org.ukui.panel") public: explicit UKuiPanelInformation(QObject *parent = 0); private: int screen_x; int screen_y; int screen_width; int screen_height; int panelposition; int panelsize; public Q_SLOTS: QVariantList GetPrimaryScreenGeometry(); QVariantList GetPrimaryScreenAvailableGeometry(); QVariantList GetPrimaryScreenPhysicalGeometry(); QString GetPanelPosition(); void setPanelInformation(int ,int ,int, int, int, int); }; #endif // UKUIPANEL_INFORMATION_H ukui-panel-3.0.6.4/panel/common_fun/listengsettings.cpp0000644000175000017500000000303514203402514021541 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #define PANEL_SETTINGS "org.ukui.panel.settings" #define PANEL_POSITION_KEY "panelposition" #define ICON_SIZE_KEY "iconsize" #define PANEL_SIZE_KEY "panelsize" ListenGsettings::ListenGsettings() { const QByteArray id(PANEL_SETTINGS); panel_gsettings = new QGSettings(id); QObject::connect(panel_gsettings, &QGSettings::changed, this, [=] (const QString &key){ if(key == PANEL_POSITION_KEY){ emit panelpositionchanged(panel_gsettings->get(PANEL_POSITION_KEY).toInt()); } if(key == ICON_SIZE_KEY){ emit iconsizechanged(panel_gsettings->get(ICON_SIZE_KEY).toInt()); } if(key == PANEL_SIZE_KEY){ emit panelsizechanged(panel_gsettings->get(PANEL_SIZE_KEY).toInt()); } }); } ukui-panel-3.0.6.4/panel/common_fun/Readme.md0000644000175000017500000000053114203402514017324 0ustar fengfeng使用工具qdbuscpp2xml从dbus.h生成XML文件; qdbuscpp2xml -M ukuipanel_infomation.h -o org.ukui.panel.information.xml B.使用工具qdbusxml2cpp从XML文件生成继承自QDBusAbstractAdaptor的类,供服务端使用 qdbusxml2cpp com.kylin.security.controller.filectrl.xml -i dbus.h -a dbus-adaptor https://blog.51cto.com/9291927/21184 ukui-panel-3.0.6.4/panel/common_fun/panel_commission.cpp0000644000175000017500000000223514203402514021653 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include class ListenGsettings : public QObject { Q_OBJECT public: ListenGsettings(); QGSettings *panel_gsettings; Q_SIGNALS: void panelsizechanged(int panelsize); void iconsizechanged(int iconsize); void panelpositionchanged(int panelposition); }; #endif // LISTENGSETTINGS_H ukui-panel-3.0.6.4/panel/common_fun/panel_commission.h0000644000175000017500000000205614203402514021321 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include class PanelCommission : public QObject { Q_OBJECT public: PanelCommission(); ~PanelCommission(); static void panelConfigFileReset(bool reset); static void panelConfigFileValueInit(bool set); }; #endif ukui-panel-3.0.6.4/panel/common_fun/dbus-adaptor.h0000644000175000017500000000421714203402514020350 0ustar fengfeng/* * This file was generated by qdbusxml2cpp version 0.8 * Command line was: qdbusxml2cpp org.ukui.panel.information.xml -i ukuipanel_infomation.h -a dbus-adaptor * * qdbusxml2cpp is Copyright (C) 2020 The Qt Company Ltd. * * This is an auto-generated file. * This file may have been hand-edited. Look for HAND-EDIT comments * before re-generating it. */ #ifndef DBUS-ADAPTOR_H #define DBUS-ADAPTOR_H #include #include #include "ukuipanel_infomation.h" QT_BEGIN_NAMESPACE class QByteArray; template class QList; template class QMap; class QString; class QStringList; class QVariant; QT_END_NAMESPACE /* * Adaptor class for interface org.ukui.panel */ class PanelAdaptor: public QDBusAbstractAdaptor { Q_OBJECT Q_CLASSINFO("D-Bus Interface", "org.ukui.panel") Q_CLASSINFO("D-Bus Introspection", "" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" "") public: PanelAdaptor(QObject *parent); virtual ~PanelAdaptor(); public: // PROPERTIES public Q_SLOTS: // METHODS QString GetPanelPosition(); QVariantList GetPrimaryScreenAvailableGeometry(); QVariantList GetPrimaryScreenGeometry(); QVariantList GetPrimaryScreenPhysicalGeometry(); void setPanelInformation(int in0, int in1, int in2, int in3, int in4, int in5); Q_SIGNALS: // SIGNALS }; #endif ukui-panel-3.0.6.4/panel/common_fun/dbus-adaptor.cpp0000644000175000017500000000421614203402514020702 0ustar fengfeng/* * This file was generated by qdbusxml2cpp version 0.8 * Command line was: qdbusxml2cpp org.ukui.panel.information.xml -i ukuipanel_infomation.h -a dbus-adaptor * * qdbusxml2cpp is Copyright (C) 2020 The Qt Company Ltd. * * This is an auto-generated file. * Do not edit! All changes made to it will be lost. */ #include "dbus-adaptor.h" #include #include #include #include #include #include #include /* * Implementation of adaptor class PanelAdaptor */ PanelAdaptor::PanelAdaptor(QObject *parent) : QDBusAbstractAdaptor(parent) { // constructor setAutoRelaySignals(true); } PanelAdaptor::~PanelAdaptor() { // destructor } QString PanelAdaptor::GetPanelPosition() { // handle method call org.ukui.panel.GetPanelPosition QString out0; QMetaObject::invokeMethod(parent(), "GetPanelPosition", Q_RETURN_ARG(QString, out0)); return out0; } QVariantList PanelAdaptor::GetPrimaryScreenAvailableGeometry() { // handle method call org.ukui.panel.GetPrimaryScreenAvailableGeometry QVariantList out0; QMetaObject::invokeMethod(parent(), "GetPrimaryScreenAvailableGeometry", Q_RETURN_ARG(QVariantList, out0)); return out0; } QVariantList PanelAdaptor::GetPrimaryScreenGeometry() { // handle method call org.ukui.panel.GetPrimaryScreenGeometry QVariantList out0; QMetaObject::invokeMethod(parent(), "GetPrimaryScreenGeometry", Q_RETURN_ARG(QVariantList, out0)); return out0; } QVariantList PanelAdaptor::GetPrimaryScreenPhysicalGeometry() { // handle method call org.ukui.panel.GetPrimaryScreenPhysicalGeometry QVariantList out0; QMetaObject::invokeMethod(parent(), "GetPrimaryScreenPhysicalGeometry", Q_RETURN_ARG(QVariantList, out0)); return out0; } void PanelAdaptor::setPanelInformation(int in0, int in1, int in2, int in3, int in4, int in5) { // handle method call org.ukui.panel.setPanelInformation QMetaObject::invokeMethod(parent(), "setPanelInformation", Q_ARG(int, in0), Q_ARG(int, in1), Q_ARG(int, in2), Q_ARG(int, in3), Q_ARG(int, in4), Q_ARG(int, in5)); } ukui-panel-3.0.6.4/panel/common_fun/org.ukui.panel.information.xml0000644000175000017500000000156514203402514023524 0ustar fengfeng ukui-panel-3.0.6.4/panel/panelpluginsmodel.cpp0000644000175000017500000003213414203402514017677 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2011 Razor team * Authors: * Alexander Sokoloff * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "panelpluginsmodel.h" #include "plugin.h" #include "iukuipanelplugin.h" #include "ukuipanel.h" #include "ukuipanelapplication.h" #include #include #include "common/ukuisettings.h" #include #define CONFIG_FILE_BACKUP "/usr/share/ukui/panel.conf" PanelPluginsModel::PanelPluginsModel(UKUIPanel * panel, QString const & namesKey, QStringList const & desktopDirs, QObject * parent/* = nullptr*/) : QAbstractListModel{parent}, mNamesKey(namesKey), mPanel(panel) { loadPlugins(desktopDirs); } PanelPluginsModel::~PanelPluginsModel() { qDeleteAll(plugins()); } int PanelPluginsModel::rowCount(const QModelIndex & parent/* = QModelIndex()*/) const { return QModelIndex() == parent ? mPlugins.size() : 0; } QVariant PanelPluginsModel::data(const QModelIndex & index, int role/* = Qt::DisplayRole*/) const { Q_ASSERT(QModelIndex() == index.parent() && 0 == index.column() && mPlugins.size() > index.row() ); pluginslist_t::const_reference plugin = mPlugins[index.row()]; QVariant ret; switch (role) { case Qt::DisplayRole: if (plugin.second.isNull()) ret = QString("Unknown (%1)").arg(plugin.first); else ret = QString("%1 (%2)").arg(plugin.second->name(), plugin.first); break; case Qt::DecorationRole: if (plugin.second.isNull()) ret = XdgIcon::fromTheme("preferences-plugin"); else ret = plugin.second->desktopFile().icon(XdgIcon::fromTheme("preferences-plugin")); break; case Qt::UserRole: ret = QVariant::fromValue(const_cast(plugin.second.data())); break; } return ret; } Qt::ItemFlags PanelPluginsModel::flags(const QModelIndex & index) const { return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemNeverHasChildren; } QStringList PanelPluginsModel::pluginNames() const { QStringList names; for (auto const & p : mPlugins) names.append(p.first); return names; } QList PanelPluginsModel::plugins() const { QList plugins; for (auto const & p : mPlugins) if (!p.second.isNull()) plugins.append(p.second.data()); return plugins; } Plugin* PanelPluginsModel::pluginByName(QString name) const { for (auto const & p : mPlugins) if (p.first == name) return p.second.data(); return nullptr; } Plugin const * PanelPluginsModel::pluginByID(QString id) const { for (auto const & p : mPlugins) { Plugin *plugin = p.second.data(); if (plugin && plugin->desktopFile().id() == id) return plugin; } return nullptr; } void PanelPluginsModel::addPlugin(const UKUi::PluginInfo &desktopFile) { if (dynamic_cast(qApp)->isPluginSingletonAndRunnig(desktopFile.id())) return; QString name = findNewPluginSettingsGroup(desktopFile.id()); QPointer plugin = loadPlugin(desktopFile, name); if (plugin.isNull()) return; qDebug()<< plugin->name()<settings()->setValue(mNamesKey, pluginNames()); emit pluginAdded(plugin.data()); } void PanelPluginsModel::removePlugin(pluginslist_t::iterator plugin) { if (mPlugins.end() != plugin) { mPanel->settings()->remove(plugin->first); Plugin * p = plugin->second.data(); const int row = plugin - mPlugins.begin(); beginRemoveRows(QModelIndex(), row, row); mPlugins.erase(plugin); endRemoveRows(); emit pluginRemoved(p); // p can be nullptr mPanel->settings()->setValue(mNamesKey, pluginNames()); if (nullptr != p) p->deleteLater(); } } void PanelPluginsModel::removePlugin() { Plugin * p = qobject_cast(sender()); auto plugin = std::find_if(mPlugins.begin(), mPlugins.end(), [p] (pluginslist_t::const_reference obj) { return p == obj.second; }); removePlugin(std::move(plugin)); } void PanelPluginsModel::movePlugin(Plugin * plugin, QString const & nameAfter) { //merge list of plugins (try to preserve original position) //subtract mPlugin.begin() from the found Plugins to get the model index const int from = std::find_if(mPlugins.begin(), mPlugins.end(), [plugin] (pluginslist_t::const_reference obj) { return plugin == obj.second.data(); }) - mPlugins.begin(); const int to = std::find_if(mPlugins.begin(), mPlugins.end(), [nameAfter] (pluginslist_t::const_reference obj) { return nameAfter == obj.first; }) - mPlugins.begin(); /* 'from' is the current position of the Plugin to be moved ("moved Plugin"), * 'to' is the position of the Plugin behind the one that is being moved * ("behind Plugin"). There are several cases to distinguish: * 1. from > to: The moved Plugin had been behind the behind Plugin before * and is moved to the front of the behind Plugin. The moved Plugin will * be inserted at position 'to', the behind Plugin and all the following * Plugins (until the former position of the moved Plugin) will increment * their indexes. * 2. from < to: The moved Plugin had already been located before the * behind Plugin. In this case, the move operation only reorders the * Plugins before the behind Plugin. All the Plugins between the moved * Plugin and the behind Plugin will decrement their index. Therefore, the * movedPlugin will not be at position 'to' but rather on position 'to-1'. * 3. from == to: This does not make sense, we catch this case to prevent * errors. * 4. from == to-1: The moved Plugin has not moved because it had already * been located in front of the behind Plugin. */ const int to_plugins = from < to ? to - 1 : to; if (from != to && from != to_plugins) { /* Although the new position of the moved Plugin will be 'to-1' if * from < to, we insert 'to' here. This is exactly how it is done * in the Qt documentation. */ beginMoveRows(QModelIndex(), from, from, QModelIndex(), to); // For the QList::move method, use the right position mPlugins.move(from, to_plugins); endMoveRows(); emit pluginMoved(plugin); mPanel->settings()->setValue(mNamesKey, pluginNames()); } } void PanelPluginsModel::loadPlugins(QStringList const & desktopDirs) { QSettings backup_qsettings(CONFIG_FILE_BACKUP,QSettings::IniFormat); QStringList plugin_names = backup_qsettings.value(mNamesKey).toStringList(); #ifdef DEBUG_PLUGIN_LOADTIME QElapsedTimer timer; timer.start(); qint64 lastTime = 0; #endif for (auto const & name : plugin_names) { pluginslist_t::iterator i = mPlugins.insert(mPlugins.end(), {name, nullptr}); QString type = backup_qsettings.value(name + "/type").toString(); if (type.isEmpty()) { qWarning() << QString("Section \"%1\" not found in %2.").arg(name, backup_qsettings.fileName()); continue; } #ifdef WITH_SCREENSAVER_FALLBACK if (QStringLiteral("screensaver") == type) { //plugin-screensaver was dropped //convert settings to plugin-quicklaunch const QString & lock_desktop = QStringLiteral(UKUI_LOCK_DESKTOP); qWarning().noquote() << "Found deprecated plugin of type 'screensaver', migrating to 'quicklaunch' with '" << lock_desktop << '\''; type = QStringLiteral("quicklaunch"); UKUi::Settings * settings = mPanel->settings(); settings->beginGroup(name); settings->remove(QString{});//remove all existing keys settings->setValue(QStringLiteral("type"), type); settings->beginWriteArray(QStringLiteral("apps"), 1); settings->setArrayIndex(0); settings->setValue(QStringLiteral("desktop"), lock_desktop); settings->endArray(); settings->endGroup(); } #endif UKUi::PluginInfoList list = UKUi::PluginInfo::search(desktopDirs, "UKUIPanel/Plugin", QString("%1.desktop").arg(type)); if( !list.count()) { qWarning() << QString("Plugin \"%1\" not found.").arg(type); continue; } i->second = loadPlugin(list.first(), name); #ifdef DEBUG_PLUGIN_LOADTIME qDebug() << "load plugin" << type << "takes" << (timer.elapsed() - lastTime) << "ms"; lastTime = timer.elapsed(); #endif } } QPointer PanelPluginsModel::loadPlugin(UKUi::PluginInfo const & desktopFile, QString const & settingsGroup) { std::unique_ptr plugin(new Plugin(desktopFile, mPanel->settings(), settingsGroup, mPanel)); if (plugin->isLoaded()) { connect(mPanel, &UKUIPanel::realigned, plugin.get(), &Plugin::realign); connect(plugin.get(), &Plugin::remove, this, static_cast(&PanelPluginsModel::removePlugin)); return plugin.release(); } return nullptr; } QString PanelPluginsModel::findNewPluginSettingsGroup(const QString &pluginType) const { QStringList groups = mPanel->settings()->childGroups(); groups.sort(); // Generate new section name QString pluginName = QString("%1").arg(pluginType); if (!groups.contains(pluginName)) return pluginName; else { for (int i = 2; true; ++i) { pluginName = QString("%1%2").arg(pluginType).arg(i); if (!groups.contains(pluginName)) return pluginName; } } } bool PanelPluginsModel::isIndexValid(QModelIndex const & index) const { return index.isValid() && QModelIndex() == index.parent() && 0 == index.column() && mPlugins.size() > index.row(); } void PanelPluginsModel::onMovePluginUp(QModelIndex const & index) { if (!isIndexValid(index)) return; const int row = index.row(); if (0 >= row) return; //can't move up beginMoveRows(QModelIndex(), row, row, QModelIndex(), row - 1); mPlugins.swap(row - 1, row); endMoveRows(); pluginslist_t::const_reference moved_plugin = mPlugins[row - 1]; pluginslist_t::const_reference prev_plugin = mPlugins[row]; emit pluginMoved(moved_plugin.second.data()); //emit signal for layout only in case both plugins are loaded/displayed if (!moved_plugin.second.isNull() && !prev_plugin.second.isNull()) emit pluginMovedUp(moved_plugin.second.data()); mPanel->settings()->setValue(mNamesKey, pluginNames()); } void PanelPluginsModel::onMovePluginDown(QModelIndex const & index) { if (!isIndexValid(index)) return; const int row = index.row(); if (mPlugins.size() <= row + 1) return; //can't move down beginMoveRows(QModelIndex(), row, row, QModelIndex(), row + 2); mPlugins.swap(row, row + 1); endMoveRows(); pluginslist_t::const_reference moved_plugin = mPlugins[row + 1]; pluginslist_t::const_reference next_plugin = mPlugins[row]; emit pluginMoved(moved_plugin.second.data()); //emit signal for layout only in case both plugins are loaded/displayed if (!moved_plugin.second.isNull() && !next_plugin.second.isNull()) emit pluginMovedUp(next_plugin.second.data()); mPanel->settings()->setValue(mNamesKey, pluginNames()); } void PanelPluginsModel::onConfigurePlugin(QModelIndex const & index) { if (!isIndexValid(index)) return; Plugin * const plugin = mPlugins[index.row()].second.data(); if (nullptr != plugin && (IUKUIPanelPlugin::HaveConfigDialog & plugin->iPlugin()->flags())) plugin->showConfigureDialog(); } void PanelPluginsModel::onRemovePlugin(QModelIndex const & index) { if (!isIndexValid(index)) return; auto plugin = mPlugins.begin() + index.row(); if (plugin->second.isNull()) removePlugin(std::move(plugin)); else plugin->second->requestRemove(); } ukui-panel-3.0.6.4/panel/customstyle.cpp0000644000175000017500000005252514203402514016556 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA */ #include "customstyle.h" #include #include #include //#if QT_CONFIG(toolbutton) /*以下代码是为了处理toolbutton 的箭头*/ static void drawArrow(const QStyle *style, const QStyleOptionToolButton *toolbutton, const QRect &rect, QPainter *painter, const QWidget *widget = 0) { QStyle::PrimitiveElement pe; switch (toolbutton->arrowType) { case Qt::LeftArrow: pe = QStyle::PE_IndicatorArrowLeft; break; case Qt::RightArrow: pe = QStyle::PE_IndicatorArrowRight; break; case Qt::UpArrow: pe = QStyle::PE_IndicatorArrowUp; break; case Qt::DownArrow: pe = QStyle::PE_IndicatorArrowDown; break; default: return; } QStyleOption arrowOpt = *toolbutton; arrowOpt.rect = rect; style->drawPrimitive(pe, &arrowOpt, painter, widget); } //#endif // QT_CONFIG(toolbutton) CustomStyle::CustomStyle(const QString &proxyStyleName, bool multileWins, QObject *parent) : QProxyStyle (proxyStyleName) { pluginName=proxyStyleName; multileWindow=multileWins; } CustomStyle::~CustomStyle() { }; /*Draws the given control using the provided painter with the style options specified by option.*/ void CustomStyle::drawComplexControl(QStyle::ComplexControl cc, const QStyleOptionComplex *opt, QPainter *p, const QWidget *widget) const { // if(control == CC_ToolButton) // { // /// 我们需要获取ToolButton的详细信息,通过qstyleoption_cast可以得到 // /// 对应的option,通过拷贝构造函数得到一CustomStyle份备份用于绘制子控件 // /// 我们一般不用在意option是怎么得到的,大部分的Qt控件都能够提供了option的init方法 // } switch (cc) { case CC_ToolButton: if (const QStyleOptionToolButton *toolbutton = qstyleoption_cast(opt)) { QRect button, menuarea; button = proxy()->subControlRect(cc, toolbutton, SC_ToolButton, widget); menuarea = proxy()->subControlRect(cc, toolbutton, SC_ToolButtonMenu, widget); State bflags = toolbutton->state & ~State_Sunken; if (bflags & State_AutoRaise) { if (!(bflags & State_MouseOver) || !(bflags & State_Enabled)) { bflags &= ~State_Raised; } } State mflags = bflags; if (toolbutton->state & State_Sunken) { if (toolbutton->activeSubControls & SC_ToolButton) bflags |= State_Sunken; mflags |= State_Sunken; } QStyleOption tool = *toolbutton; if (toolbutton->subControls & SC_ToolButton) { if (bflags & (State_Sunken | State_On | State_Raised)) { tool.rect = button; tool.state = bflags; proxy()->drawPrimitive(PE_PanelButtonTool, &tool, p, widget); } } if (toolbutton->state & State_HasFocus) { QStyleOptionFocusRect fr; fr.QStyleOption::operator=(*toolbutton); fr.rect.adjust(3, 3, -3, -3); if (toolbutton->features & QStyleOptionToolButton::MenuButtonPopup) fr.rect.adjust(0, 0, -proxy()->pixelMetric(QStyle::PM_MenuButtonIndicator, toolbutton, widget), 0); proxy()->drawPrimitive(PE_FrameFocusRect, &fr, p, widget); } QStyleOptionToolButton label = *toolbutton; label.state = bflags; int fw = proxy()->pixelMetric(PM_DefaultFrameWidth, opt, widget); label.rect = button.adjusted(fw, fw, -fw, -fw); proxy()->drawControl(CE_ToolButtonLabel, &label, p, widget); if (toolbutton->subControls & SC_ToolButtonMenu) { tool.rect = menuarea; tool.state = mflags; if (mflags & (State_Sunken | State_On | State_Raised)) proxy()->drawPrimitive(PE_IndicatorButtonDropDown, &tool, p, widget); proxy()->drawPrimitive(PE_IndicatorArrowDown, &tool, p, widget); } else if (toolbutton->features & QStyleOptionToolButton::HasMenu) { int mbi = proxy()->pixelMetric(PM_MenuButtonIndicator, toolbutton, widget); QRect ir = toolbutton->rect; QStyleOptionToolButton newBtn = *toolbutton; newBtn.rect = QRect(ir.right() + 5 - mbi, ir.y() + ir.height() - mbi + 4, mbi - 6, mbi - 6); newBtn.rect = visualRect(toolbutton->direction, button, newBtn.rect); //proxy()->drawPrimitive(PE_IndicatorArrowDown, &newBtn, p, widget); } } return; default: break; } return QProxyStyle::drawComplexControl(cc, opt, p, widget); } /*下面对于CE_ToolButtonLabel 的处理是因为quicklaunch 插件出现了箭头*/ void CustomStyle::drawControl(QStyle::ControlElement element, const QStyleOption *opt, QPainter *p, const QWidget *widget) const { switch (element) { case CE_PushButton: if (const QStyleOptionButton *btn = qstyleoption_cast(opt)) { proxy()->drawControl(CE_PushButtonBevel, btn, p, widget); QStyleOptionButton subopt = *btn; subopt.rect = subElementRect(SE_PushButtonContents, btn, widget); proxy()->drawControl(CE_PushButtonLabel, &subopt, p, widget); } case CE_PushButtonBevel: { if (const QStyleOptionButton *btn = qstyleoption_cast(opt)) { QRect br = btn->rect; int dbi = proxy()->pixelMetric(PM_ButtonDefaultIndicator, btn, widget); if (btn->features & QStyleOptionButton::AutoDefaultButton) br.setCoords(br.left() + dbi, br.top() + dbi, br.right() - dbi, br.bottom() - dbi); QStyleOptionButton tmpBtn = *btn; tmpBtn.rect = br; drawPrimitive(PE_PanelButtonCommand, &tmpBtn, p, widget); return; // qDebug()<<" ************** PushButton *********************** "; // p->save(); // // painter->setRenderHint(QPainter::Antialiasing,true); // // painter->setPen(Qt::NoPen); // // painter->drawRoundedRect(option->rect,6,6); // if (opt->state & State_MouseOver) { // if (opt->state & State_Sunken) { // p->setRenderHint(QPainter::Antialiasing,true); // p->setPen(Qt::NoPen); // p->setBrush(QColor(0xff,0xff,0xff)); // p->drawRoundedRect(opt->rect.adjusted(2,2,-2,-2),6,6); // } else { // p->setRenderHint(QPainter::Antialiasing,true); // p->setPen(Qt::NoPen); // p->setBrush(QColor(0xff,0xff,0xff)); // p->drawRoundedRect(opt->rect.adjusted(2,2,-2,-2),6,6); // } // } // p->restore(); // return; } break; } case CE_ToolButtonLabel: { if (const QStyleOptionToolButton *toolbutton = qstyleoption_cast(opt)) { QRect rect = toolbutton->rect; int shiftX = 0; int shiftY = 0; // if (toolbutton->state & (State_Sunken | State_On)) { // shiftX = proxy()->pixelMetric(PM_ButtonShiftHorizontal, toolbutton, widget); // shiftY = proxy()->pixelMetric(PM_ButtonShiftVertical, toolbutton, widget); // } // Arrow type always overrules and is always shown bool hasArrow = toolbutton->features & QStyleOptionToolButton::Arrow; if (((!hasArrow && toolbutton->icon.isNull()) && !toolbutton->text.isEmpty()) || toolbutton->toolButtonStyle == Qt::ToolButtonTextOnly) { int alignment = Qt::AlignCenter | Qt::TextShowMnemonic; if (!proxy()->styleHint(SH_UnderlineShortcut, opt, widget)) alignment |= Qt::TextHideMnemonic; rect.translate(shiftX, shiftY); p->setFont(toolbutton->font); proxy()->drawItemText(p, rect, alignment, toolbutton->palette, opt->state & State_Enabled, toolbutton->text, QPalette::ButtonText); } else { QPixmap pm; QSize pmSize = toolbutton->iconSize; if (!toolbutton->icon.isNull()) { QIcon::State state = toolbutton->state & State_On ? QIcon::On : QIcon::Off; QIcon::Mode mode; if (!(toolbutton->state & State_Enabled)) mode = QIcon::Disabled; else if ((opt->state & State_MouseOver) && (opt->state & State_AutoRaise)) mode = QIcon::Active; else mode = QIcon::Normal; pm = toolbutton->icon.pixmap(widget->window()->windowHandle(), toolbutton->rect.size().boundedTo(toolbutton->iconSize), mode, state); pmSize = pm.size() / pm.devicePixelRatio(); } if (toolbutton->toolButtonStyle != Qt::ToolButtonIconOnly) { p->setFont(toolbutton->font); QRect pr = rect, tr = rect; int alignment = Qt::TextShowMnemonic; if (!proxy()->styleHint(SH_UnderlineShortcut, opt, widget)) alignment |= Qt::TextHideMnemonic; if (toolbutton->toolButtonStyle == Qt::ToolButtonTextUnderIcon) { pr.setHeight(pmSize.height() + 4); //### 4 is currently hardcoded in QToolButton::sizeHint() tr.adjust(0, pr.height() - 1, 0, -1); pr.translate(shiftX, shiftY); if (!hasArrow) { proxy()->drawItemPixmap(p, pr, Qt::AlignCenter, pm); } else { drawArrow(proxy(), toolbutton, pr, p, widget); } alignment |= Qt::AlignCenter; } else { pr.setWidth(pmSize.width() + 4); //### 4 is currently hardcoded in QToolButton::sizeHint() tr.adjust(pr.width(), 0, 0, 0); pr.translate(shiftX, shiftY); if (!hasArrow) { proxy()->drawItemPixmap(p, QStyle::visualRect(opt->direction, rect, pr), Qt::AlignCenter, pm); } else { drawArrow(proxy(), toolbutton, pr, p, widget); } alignment |= Qt::AlignLeft | Qt::AlignVCenter; } tr.translate(shiftX, shiftY); //const QString text = d->toolButtonElideText(toolbutton, tr, alignment); proxy()->drawItemText(p, QStyle::visualRect(opt->direction, rect, tr), alignment, toolbutton->palette, toolbutton->state & State_Enabled, toolbutton->text, QPalette::ButtonText); } else { rect.translate(shiftX, shiftY); if (hasArrow) { drawArrow(proxy(), toolbutton, rect, p, widget); } else { proxy()->drawItemPixmap(p, rect, Qt::AlignCenter, pm); } } } } return; } default: break; } return QProxyStyle::drawControl(element, opt, p, widget); } void CustomStyle::drawItemPixmap(QPainter *painter, const QRect &rectangle, int alignment, const QPixmap &pixmap) const { return QProxyStyle::drawItemPixmap(painter, rectangle, alignment, pixmap); } void CustomStyle::drawItemText(QPainter *painter, const QRect &rectangle, int alignment, const QPalette &palette, bool enabled, const QString &text, QPalette::ColorRole textRole) const { return QProxyStyle::drawItemText(painter, rectangle, alignment, palette, enabled, text, textRole); } //绘制简单的颜色圆角等 void CustomStyle::drawPrimitive(QStyle::PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const { switch (element) { /*绘制 ToolButton * 任务栏的不同插件需要的样式存在差异 * 在同一个PE中有两个toolbutton 的样式 */ case PE_PanelButtonTool:{ if(QString::compare(pluginName,"taskbutton")==0) { painter->save(); painter->setRenderHint(QPainter::Antialiasing,true); painter->setPen(Qt::NoPen); painter->setBrush(QColor(0xff,0xff,0xff,0x14)); if (option->state & State_Sunken) { painter->setBrush(QColor(0xff,0xff,0xff,0x0f)); } else if (option->state & State_MouseOver) { painter->setBrush(QColor(0xff,0xff,0xff,0x1f)); } else if (option->state & State_On) { painter->setBrush(QColor(0xff,0xff,0xff,0x33)); } painter->drawRoundedRect(option->rect.adjusted(2,2,-2,-2),6,6); painter->restore(); /*buttom center x:22.5 y:42*/ if(multileWindow) { painter->save(); painter->setRenderHint(QPainter::Antialiasing, true); painter->setPen(Qt::NoPen); painter->setBrush(option->palette.color(QPalette::Highlight)); painter->drawEllipse(option->rect.topLeft() + QPointF(8.5, 4.5), 2.5, 2.5); painter->setBrush(option->palette.color(QPalette::Highlight).light(125)); painter->drawEllipse(option->rect.topLeft() + QPointF(4.5, 4.5), 2.5, 2.5); painter->restore(); } return; } else if(QString::compare(pluginName,"closebutton")==0) { painter->save(); painter->setRenderHint(QPainter::Antialiasing,true); painter->setPen(Qt::NoPen); // painter->setBrush(QColor(0xff,0xff,0xff,0xffoption)); painter->drawRoundedRect(option->rect,6,6); if (option->state & State_MouseOver) { if (option->state & State_Sunken) { painter->setRenderHint(QPainter::Antialiasing,true); painter->setPen(Qt::NoPen); painter->setBrush(QColor(0xd7,0x34,0x35)); painter->drawRoundedRect(option->rect,6,6); } else { painter->setRenderHint(QPainter::Antialiasing,true); painter->setPen(Qt::NoPen); painter->setBrush(QColor(0xf0,0x41,0x34)); painter->drawRoundedRect(option->rect,4,4); } } painter->restore(); return; } else { painter->save(); painter->setRenderHint(QPainter::Antialiasing,true); painter->setPen(Qt::NoPen); painter->drawRoundedRect(option->rect,6,6); if (option->state & State_MouseOver) { if (option->state & State_Sunken) { painter->setRenderHint(QPainter::Antialiasing,true); painter->setPen(Qt::NoPen); painter->setBrush(QColor(0xff,0xff,0xff,0x0f)); painter->drawRoundedRect(option->rect,6,6); } else { painter->setRenderHint(QPainter::Antialiasing,true); painter->setPen(Qt::NoPen); painter->setBrush(QColor(0xff,0xff,0xff,0x1f)); painter->drawRoundedRect(option->rect.adjusted(2,2,-2,-2),6,6); } } painter->restore(); return; } } case PE_PanelButtonCommand:{ if(const QStyleOptionButton *button = qstyleoption_cast(option)) { painter->save(); if (option->state & State_MouseOver) { if (option->state & State_Sunken) { painter->setRenderHint(QPainter::Antialiasing,true); painter->setPen(Qt::NoPen); painter->setBrush(QColor(0xff,0xff,0xff,0x0f)); painter->drawRoundedRect(button->rect,6,6); } else { painter->setRenderHint(QPainter::Antialiasing,true); painter->setPen(Qt::NoPen); painter->setBrush(QColor(0xff,0xff,0xff,0x1f)); painter->drawRoundedRect(button->rect.adjusted(2,2,-2,-2),6,6); } } painter->restore(); return; } break; }break; } return QProxyStyle::drawPrimitive(element, option, painter, widget); } QPixmap CustomStyle::generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap, const QStyleOption *option) const { return QProxyStyle::generatedIconPixmap(iconMode, pixmap, option); } QStyle::SubControl CustomStyle::hitTestComplexControl(QStyle::ComplexControl control, const QStyleOptionComplex *option, const QPoint &position, const QWidget *widget) const { return QProxyStyle::hitTestComplexControl(control, option, position, widget); } QRect CustomStyle::itemPixmapRect(const QRect &rectangle, int alignment, const QPixmap &pixmap) const { return QProxyStyle::itemPixmapRect(rectangle, alignment, pixmap); } QRect CustomStyle::itemTextRect(const QFontMetrics &metrics, const QRect &rectangle, int alignment, bool enabled, const QString &text) const { return QProxyStyle::itemTextRect(metrics, rectangle, alignment, enabled, text); } // int CustomStyle::pixelMetric(QStyle::PixelMetric metric, const QStyleOption *option, const QWidget *widget) const { switch (metric){ case PM_ToolBarIconSize:{ return (int)48*qApp->devicePixelRatio(); } default: break; } return QProxyStyle::pixelMetric(metric, option, widget); } /*使悬浮点击等样式生效*/ void CustomStyle::polish(QWidget *widget) { widget->setAttribute(Qt::WA_Hover); return QProxyStyle::polish(widget); } void CustomStyle::polish(QApplication *application) { return QProxyStyle::polish(application); } // void CustomStyle::polish(QPalette &palette) { // return QProxyStyle::polish(palette); // QProxyStyle::polish(palette); // palette.setBrush(QPalette::Foreground, Qt::black); QColor lightBlue(200, 0, 0); palette.setBrush(QPalette::Highlight, lightBlue); } void CustomStyle::unpolish(QWidget *widget) { return QProxyStyle::unpolish(widget); } void CustomStyle::unpolish(QApplication *application) { return QProxyStyle::unpolish(application); } QSize CustomStyle::sizeFromContents(QStyle::ContentsType type, const QStyleOption *option, const QSize &contentsSize, const QWidget *widget) const { return QProxyStyle::sizeFromContents(type, option, contentsSize, widget); } QIcon CustomStyle::standardIcon(QStyle::StandardPixmap standardIcon, const QStyleOption *option, const QWidget *widget) const { return QProxyStyle::standardIcon(standardIcon, option, widget); } QPalette CustomStyle::standardPalette() const { return QProxyStyle::standardPalette(); } //如果需要背景透明也许需要用到这个函数 int CustomStyle::styleHint(QStyle::StyleHint hint, const QStyleOption *option, const QWidget *widget, QStyleHintReturn *returnData) const { switch (hint) { /// 让ScrollView viewport的绘制区域包含scrollbar和corner widget /// 这个例子中没有什么作用,如果我们需要绘制一个背景透明的滚动条 /// 这个style hint对我们的意义应该很大,因为我们希望视图能够帮助 /// 我们填充滚动条的背景区域,否则当背景透明时底下会出现明显的分割 case SH_ScrollView_FrameOnlyAroundContents: { return false; } default: break; } return QProxyStyle::styleHint(hint, option, widget, returnData); } QRect CustomStyle::subControlRect(QStyle::ComplexControl control, const QStyleOptionComplex *option, QStyle::SubControl subControl, const QWidget *widget) const { return QProxyStyle::subControlRect(control, option, subControl, widget); } QRect CustomStyle::subElementRect(QStyle::SubElement element, const QStyleOption *option, const QWidget *widget) const { return QProxyStyle::subElementRect(element, option, widget); } ukui-panel-3.0.6.4/panel/pluginmoveprocessor.cpp0000644000175000017500000002075414203402514020307 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2011 Razor team * Authors: * Alexander Sokoloff * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "pluginmoveprocessor.h" #include "plugin.h" #include "ukuipanellayout.h" #include /************************************************ ************************************************/ PluginMoveProcessor::PluginMoveProcessor(UKUIPanelLayout *layout, Plugin *plugin): QWidget(plugin), mLayout(layout), mPlugin(plugin) { mDestIndex = mLayout->indexOf(plugin); grabKeyboard(); } /************************************************ ************************************************/ PluginMoveProcessor::~PluginMoveProcessor() { } /************************************************ ************************************************/ void PluginMoveProcessor::start() { // We have not memoryleaks there. // The animation will be automatically deleted when stopped. CursorAnimation *cursorAnimation = new CursorAnimation(); connect(cursorAnimation, SIGNAL(finished()), this, SLOT(doStart())); cursorAnimation->setEasingCurve(QEasingCurve::InOutQuad); cursorAnimation->setDuration(150); cursorAnimation->setStartValue(QCursor::pos()); cursorAnimation->setEndValue(mPlugin->mapToGlobal(mPlugin->rect().center())); cursorAnimation->start(QAbstractAnimation::DeleteWhenStopped); cursorAnimation->deleteLater(); } /************************************************ ************************************************/ void PluginMoveProcessor::doStart() { setMouseTracking(true); show(); // Only visible widgets can grab mouse input. grabMouse(mLayout->isHorizontal() ? Qt::SizeHorCursor : Qt::SizeVerCursor); } /************************************************ ************************************************/ void PluginMoveProcessor::mouseMoveEvent(QMouseEvent *event) { QPoint mouse = mLayout->parentWidget()->mapFromGlobal(event->globalPos()); qDebug()<<"mouse:"<itemAt(pos.index + 1); } else { prevItem = mLayout->itemAt(pos.index - 1); nextItem = pos.item; mDestIndex = pos.index; } bool plugSep = mPlugin->isSeparate(); bool prevSep =UKUIPanelLayout::itemIsSeparate(prevItem); bool nextSep =UKUIPanelLayout::itemIsSeparate(nextItem); if (!nextItem) { if (mLayout->isHorizontal()) drawMark(prevItem, prevSep ? RightMark : BottomMark); else drawMark(prevItem, prevSep ? BottomMark : RightMark); return; } if (mLayout->lineCount() == 1) { if (mLayout->isHorizontal()) drawMark(nextItem, LeftMark); else drawMark(nextItem, TopMark); return; } if (!prevItem) { if (mLayout->isHorizontal()) drawMark(nextItem, nextSep ? LeftMark : TopMark); else drawMark(nextItem, nextSep ? TopMark : LeftMark); return; } // We prefer to draw line at the top/left of next item. // But if next item and moved plugin have different types (separate an not) and // previous item hase same type as moved plugin we draw line at the end of previous one. if (plugSep != nextSep && plugSep == prevSep) { if (mLayout->isHorizontal()) drawMark(prevItem, prevSep ? RightMark : BottomMark); else drawMark(prevItem, prevSep ? BottomMark : RightMark); } else { if (mLayout->isHorizontal()) drawMark(nextItem, nextSep ? LeftMark : TopMark); else drawMark(nextItem, nextSep ? TopMark : LeftMark); } } /************************************************ ************************************************/ PluginMoveProcessor::MousePosInfo PluginMoveProcessor::itemByMousePos(const QPoint mouse) const { MousePosInfo ret; for (int i = mLayout->count()-1; i > -1; --i) { QLayoutItem *item = mLayout->itemAt(i); QRect itemRect = item->geometry(); if (mouse.x() > itemRect.left() && mouse.y() > itemRect.top()) { ret.index = i; ret.item = item; if (mLayout->isHorizontal()) { ret.after =UKUIPanelLayout::itemIsSeparate(item) ? mouse.x() > itemRect.center().x() : mouse.y() > itemRect.center().y() ; } else { ret.after =UKUIPanelLayout::itemIsSeparate(item) ? mouse.y() > itemRect.center().y() : mouse.x() > itemRect.center().x() ; } return ret; } } ret.index = 0; ret.item = mLayout->itemAt(0); ret.after = false; return ret; } /************************************************ ************************************************/ void PluginMoveProcessor::drawMark(QLayoutItem *item, MarkType markType) { QWidget *widget = (item) ? item->widget() : 0; static QWidget *prevWidget = 0; if (prevWidget && prevWidget != widget) prevWidget->setStyleSheet(""); prevWidget = widget; if (!widget) return; QString border1; QString border2; switch(markType) { case TopMark: border1 = "top"; border2 = "bottom"; break; case BottomMark: border1 = "bottom"; border2 = "top"; break; case LeftMark: border1 = "left"; border2 = "right"; break; case RightMark: border1 = "right"; border2 = "left"; break; } widget->setStyleSheet(QString("#%1 {" "border-%2: 2px solid rgba(%4, %5, %6, %7); " "border-%3: -2px solid; " "background-color: transparent; }") .arg(widget->objectName()) .arg(border1) .arg(border2) .arg(Plugin::moveMarkerColor().red()) .arg(Plugin::moveMarkerColor().green()) .arg(Plugin::moveMarkerColor().blue()) .arg(Plugin::moveMarkerColor().alpha()) ); } /************************************************ ************************************************/ void PluginMoveProcessor::mousePressEvent(QMouseEvent *event) { event->accept(); } /************************************************ ************************************************/ void PluginMoveProcessor::mouseReleaseEvent(QMouseEvent *event) { event->accept(); releaseMouse(); setMouseTracking(false); doFinish(false); } /************************************************ ************************************************/ void PluginMoveProcessor::keyPressEvent(QKeyEvent *event) { if (event->key() == Qt::Key_Escape) { doFinish(true); return; } QWidget::keyPressEvent(event); } /************************************************ ************************************************/ void PluginMoveProcessor::doFinish(bool cancel) { releaseKeyboard(); drawMark(0, TopMark); if (!cancel) { int currentIdx = mLayout->indexOf(mPlugin); if (currentIdx == mDestIndex) return; if (mDestIndex > currentIdx) mDestIndex--; mLayout->moveItem(currentIdx, mDestIndex, true); } emit finished(); deleteLater(); } ukui-panel-3.0.6.4/panel/ukuipanelapplication_p.h0000644000175000017500000000262514203402514020364 0ustar fengfeng/* * Copyright (C) 2016 Luís Pereira * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA */ #ifndef UKUIPanelAPPLICATION_P_H #define UKUIPanelAPPLICATION_P_H #include "ukuipanelapplication.h" namespace UKUi { class Settings; } class UKUIPanelApplicationPrivate { Q_DECLARE_PUBLIC(UKUIPanelApplication) public: UKUIPanelApplicationPrivate(UKUIPanelApplication *q); ~UKUIPanelApplicationPrivate() {}; UKUi::Settings *mSettings; IUKUIPanel::Position computeNewPanelPosition(const UKUIPanel *p, const int screenNum); private: UKUIPanelApplication *const q_ptr; }; #endif // UKUIPanelAPPLICATION_P_H ukui-panel-3.0.6.4/panel/ukuipanel.cpp0000644000175000017500000017201214203402514016152 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2011 Razor team * Authors: * Alexander Sokoloff * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "ukuipanel.h" #include "ukuipanellimits.h" #include "iukuipanelplugin.h" #include "ukuipanelapplication.h" #include "ukuipanellayout.h" #include "plugin.h" #include "panelpluginsmodel.h" #include "windownotifier.h" #include "common/ukuiplugininfo.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //#include //#include #include // Turn on this to show the time required to load each plugin during startup // #define DEBUG_PLUGIN_LOADTIME #include "common_fun/ukuipanel_infomation.h" #include "common_fun/dbus-adaptor.h" #include "common_fun/panel_commission.h" #ifdef DEBUG_PLUGIN_LOADTIME #include #endif // Config keys and groups #define CFG_KEY_SCREENNUM "desktop" #define CFG_KEY_POSITION "position" #define CFG_KEY_LINECNT "lineCount" #define CFG_KEY_LENGTH "width" #define CFG_KEY_PERCENT "width-percent" #define CFG_KEY_ALIGNMENT "alignment" #define CFG_KEY_RESERVESPACE "reserve-space" #define CFG_KEY_PLUGINS "plugins" #define CFG_KEY_HIDABLE "hidable" #define CFG_KEY_VISIBLE_MARGIN "visible-margin" #define CFG_KEY_ANIMATION "animation-duration" #define CFG_KEY_SHOW_DELAY "show-delay" #define CFG_KEY_LOCKPANEL "lockPanel" #define CFG_KEY_PLUGINS_PC "plugins-pc" #define CFG_KEY_PLUGINS_PAD "plugins-pad" #define GSETTINGS_SCHEMA_SCREENSAVER "org.mate.interface" #define KEY_MODE "gtk-theme" #define PANEL_SIZE_LARGE 92 #define PANEL_SIZE_MEDIUM 70 #define PANEL_SIZE_SMALL 46 #define ICON_SIZE_LARGE 64 #define ICON_SIZE_MEDIUM 48 #define ICON_SIZE_SMALL 32 #define PANEL_SIZE_LARGE_V 70 #define PANEL_SIZE_MEDIUM_V 62 #define PANEL_SIZE_SMALL_V 47 #define POPUP_BORDER_SPACING 4 #define PANEL_SETTINGS "org.ukui.panel.settings" #define PANEL_SIZE_KEY "panelsize" #define ICON_SIZE_KEY "iconsize" #define PANEL_POSITION_KEY "panelposition" #define SHOW_TASKVIEW "showtaskview" #define SHOW_NIGHTMODE "shownightmode" #define TRANSPARENCY_SETTINGS "org.ukui.control-center.personalise" #define TRANSPARENCY_KEY "transparency" #define UKUI_SERVICE "org.gnome.SessionManager" #define UKUI_PATH "/org/gnome/SessionManager" #define UKUI_INTERFACE "org.gnome.SessionManager" /************************************************ Returns the Position by the string. String is one of "Top", "Left", "Bottom", "Right", string is not case sensitive. If the string is not correct, returns defaultValue. ************************************************/ IUKUIPanel::Position UKUIPanel::strToPosition(const QString& str, IUKUIPanel::Position defaultValue) { if (str.toUpper() == "TOP") return UKUIPanel::PositionTop; if (str.toUpper() == "LEFT") return UKUIPanel::PositionLeft; if (str.toUpper() == "RIGHT") return UKUIPanel::PositionRight; if (str.toUpper() == "BOTTOM") return UKUIPanel::PositionBottom; return defaultValue; } IUKUIPanel::Position UKUIPanel::intToPosition(const int position, IUKUIPanel::Position defaultValue) { if (position == 1) return UKUIPanel::PositionTop; if (position == 2) return UKUIPanel::PositionLeft; if (position == 3) return UKUIPanel::PositionRight; if (position == 0) return UKUIPanel::PositionBottom; return defaultValue; } /************************************************ Return string representation of the position *******************************************connect(QApplication::desktop(), &QDesktopWidget::resized, this, &UKUIPanel::ensureVisible);*****/ QString UKUIPanel::positionToStr(IUKUIPanel::Position position) { switch (position) { case UKUIPanel::PositionTop: return QString("Top"); case UKUIPanel::PositionLeft: return QString("Left"); case UKUIPanel::PositionRight: return QString("Right"); case UKUIPanel::PositionBottom: return QString("Bottom"); } return QString(); } /************************************************ ************************************************/ UKUIPanel::UKUIPanel(const QString &configGroup, UKUi::Settings *settings, QWidget *parent) : QFrame(parent), mSettings(settings), mConfigGroup(configGroup), mPlugins{nullptr}, mStandaloneWindows{new WindowNotifier}, mPanelSize(46), mIconSize(32), mLineCount(0), mLength(0), mAlignment(AlignmentLeft), mPosition(IUKUIPanel::PositionBottom), mScreenNum(0), //whatever (avoid conditional on uninitialized value) mActualScreenNum(0), mHidable(false), mVisibleMargin(true), mHidden(false), mAnimationTime(0), mReserveSpace(true), mAnimation(nullptr), mLockPanel(false) { qDebug()<<"Panel :: Constructor start"; //You can find information about the flags and widget attributes in your //Qt documentation or at https://doc.qt.io/qt-5/qt.html //Qt::FramelessWindowHint = Produces a borderless window. The user cannot //move or resize a borderless window via the window system. On X11, ... //Qt::WindowStaysOnTopHint = Informs the window system that the window //should stay on top of all other windows. Note that on ... Qt::WindowFlags flags = Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint; // NOTE: by PCMan: // In Qt 4, the window is not activated if it has Qt::WA_X11NetWmWindowTypeDock. // Since Qt 5, the default behaviour is changed. A window is always activated on mouse click. // Please see the source code of Qt5: src/plugins/platforms/xcb/qxcbwindow.cpp. // void QXcbWindow::handleButtonPressEvent(const xcb_button_press_event_t *event) // This new behaviour caused ukui bug #161 - Cannot minimize windows from panel 1 when two task managers are open // Besides, this breaks minimizing or restoring windows when clicking on the taskbar buttons. // To workaround this regression bug, we need to add this window flag here. // However, since the panel gets no keyboard focus, this may decrease accessibility since // it's not possible to use the panel with keyboards. We need to find a better solution later. /*部分组建在点击任务栏空白位置的时候,无法收回窗口,想要正常收回窗口,需要取消下面的窗口属性或者其他应用监听点击taskbar的点击信号 * 不使用此窗口属性则需要在开始菜单,任务视图,快速启动栏三个界面组件中设置 setFocusPolicy(Qt::NoFocus); */ flags |= Qt::WindowDoesNotAcceptFocus; setWindowFlags(flags); //Adds _NET_WM_WINDOW_TYPE_DOCK to the window's _NET_WM_WINDOW_TYPE X11 window property. See https://standards.freedesktop.org/wm-spec/ for more details. setAttribute(Qt::WA_X11NetWmWindowTypeDock); //Enables tooltips for inactive windows. setAttribute(Qt::WA_AlwaysShowToolTips); //Indicates that the widget should have a translucent background, i.e., any non-opaque regions of the widgets will be translucent because the widget will have an alpha channel. Setting this ... setAttribute(Qt::WA_TranslucentBackground); //Allows data from drag and drop operations to be dropped onto the widget (see QWidget::setAcceptDrops()). setAttribute(Qt::WA_AcceptDrops); setWindowTitle("UKUI Panel"); setObjectName(QString("UKUIPanel %1").arg(configGroup)); if(qgetenv("XDG_SESSION_TYPE")=="wayland") flag_hw990="hw_990"; qDebug()<<"Panel :: UKuiPanel setAttribute finished"; //初始化参数调整 PanelCommission::panelConfigFileValueInit(true); PanelCommission::panelConfigFileReset(true); qDebug()<<"Panel :: PanelCommission config finished"; //UKUIPanel (inherits QFrame) -> lav (QGridLayout) -> UKUIPanelWidget (QFrame) -> UKUIPanelLayout UKUIPanelWidget = new QFrame(this); UKUIPanelWidget->setObjectName("BackgroundWidget"); QGridLayout* lav = new QGridLayout(); lav->setContentsMargins(0, 0, 0, 0); setLayout(lav); this->layout()->addWidget(UKUIPanelWidget); mLayout = new UKUIPanelLayout(UKUIPanelWidget); connect(mLayout, &UKUIPanelLayout::pluginMoved, this, &UKUIPanel::pluginMoved); UKUIPanelWidget->setLayout(mLayout); mLayout->setLineCount(mLineCount); mDelaySave.setSingleShot(true); mDelaySave.setInterval(SETTINGS_SAVE_DELAY); connect(&mDelaySave, SIGNAL(timeout()), this, SLOT(saveSettings())); mHideTimer.setSingleShot(true); mHideTimer.setInterval(PANEL_HIDE_DELAY); connect(&mHideTimer, SIGNAL(timeout()), this, SLOT(hidePanelWork())); connectToServer(); mShowDelayTimer.setSingleShot(true); mShowDelayTimer.setInterval(PANEL_SHOW_DELAY); connect(&mShowDelayTimer, &QTimer::timeout, [this] { showPanel(mAnimationTime > 0); }); /* 监听屏幕分辨路改变resized 和屏幕数量改变screenCountChanged * 或许存在无法监听到分辨率改变的情况(qt5.6),若出现则可换成 * connect(QApplication::primaryScreen(),&QScreen::geometryChanged, this,&UKUIPanel::ensureVisible); */ connect(QApplication::desktop(), &QDesktopWidget::resized, this, &UKUIPanel::ensureVisible); connect(QApplication::desktop(), &QDesktopWidget::screenCountChanged, this, &UKUIPanel::ensureVisible); connect(qApp,&QApplication::primaryScreenChanged,this,&UKUIPanel::ensureVisible); // connecting to QDesktopWidget::workAreaResized shouldn't be necessary, // as we've already connceted to QDesktopWidget::resized, but it actually connect(QApplication::desktop(), &QDesktopWidget::workAreaResized, this, &UKUIPanel::ensureVisible); UKUIPanelApplication *a = reinterpret_cast(qApp); connect(a, &UKUIPanelApplication::primaryScreenChanged, [=]{ setPanelGeometry(); }); connect(UKUi::Settings::globalSettings(), SIGNAL(settingsChanged()), this, SLOT(update())); connect(ukuiApp, SIGNAL(themeChanged()), this, SLOT(realign())); connect(mStandaloneWindows.data(), &WindowNotifier::firstShown, [this] { showPanel(true); }); connect(mStandaloneWindows.data(), &WindowNotifier::lastHidden, this, &UKUIPanel::hidePanel); const QByteArray id(PANEL_SETTINGS); gsettings = new QGSettings(id); setPosition(0,intToPosition(gsettings->get(PANEL_POSITION_KEY).toInt(),PositionBottom),true); connect(gsettings, &QGSettings::changed, this, [=] (const QString &key){ if(key==ICON_SIZE_KEY){ setIconSize(gsettings->get(ICON_SIZE_KEY).toInt(),true); } if(key==PANEL_SIZE_KEY){ setPanelSize(gsettings->get(PANEL_SIZE_KEY).toInt(),true); } if(key == PANEL_POSITION_KEY){ setPosition(0,intToPosition(gsettings->get(PANEL_POSITION_KEY).toInt(),PositionBottom),true); } }); setPanelSize(gsettings->get(PANEL_SIZE_KEY).toInt(),true); setIconSize(gsettings->get(ICON_SIZE_KEY).toInt(),true); setPosition(0,intToPosition(gsettings->get(PANEL_POSITION_KEY).toInt(),PositionBottom),true); time = new QTimer(this); connect(time, &QTimer::timeout, this,[=] (){ mShowDelayTimer.stop(); hidePanel(); time->stop(); }); qDebug()<<"Panel :: setGeometry finished"; readSettings(); ensureVisible(); qDebug()<<"Panel :: loadPlugins start"; loadPlugins(); qDebug()<<"Panel :: loadPlugins finished"; show(); qDebug()<<"Panel :: show UKuiPanel finished"; //给session发信号,告知任务栏已经启动完成,可以启动下一个组件 QDBusInterface interface(UKUI_SERVICE, UKUI_PATH, UKUI_INTERFACE, QDBusConnection::sessionBus()); interface.call("startupfinished","ukui-panel","finish"); // show it the first time, despite setting if (mHidable) { showPanel(false); QTimer::singleShot(PANEL_HIDE_FIRST_TIME, this, SLOT(hidePanel())); } styleAdjust(); qDebug()<<"Panel :: UKuiPanel finished"; UKuiPanelInformation* dbus=new UKuiPanelInformation; new PanelAdaptor(dbus); QDBusConnection con=QDBusConnection::sessionBus(); if(!con.registerService("org.ukui.panel") || !con.registerObject("/panel/position",dbus)) { qDebug()<<"fail"; } } void UKUIPanel::readSettings() { // Read settings ...................................... mSettings->beginGroup(mConfigGroup); // Let Hidability be the first thing we read // so that every call to realign() is without side-effect mHidable = mSettings->value(CFG_KEY_HIDABLE, mHidable).toBool(); mHidden = mHidable; mVisibleMargin = mSettings->value(CFG_KEY_VISIBLE_MARGIN, mVisibleMargin).toBool(); mAnimationTime = mSettings->value(CFG_KEY_ANIMATION, mAnimationTime).toInt(); mShowDelayTimer.setInterval(mSettings->value(CFG_KEY_SHOW_DELAY, mShowDelayTimer.interval()).toInt()); // By default we are using size & count from theme. setLineCount(mSettings->value(CFG_KEY_LINECNT, PANEL_DEFAULT_LINE_COUNT).toInt(), false); setLength(mSettings->value(CFG_KEY_LENGTH, 100).toInt(), mSettings->value(CFG_KEY_PERCENT, true).toBool(), false); mScreenNum = mSettings->value(CFG_KEY_SCREENNUM, QApplication::desktop()->primaryScreen()).toInt(); // setPosition(mScreenNum, // strToPosition(mSettings->value(CFG_KEY_POSITION).toString(), PositionBottom), // false); setAlignment(Alignment(mSettings->value(CFG_KEY_ALIGNMENT, mAlignment).toInt()), false); mReserveSpace = mSettings->value(CFG_KEY_RESERVESPACE, true).toBool(); mLockPanel = mSettings->value(CFG_KEY_LOCKPANEL, false).toBool(); mSettings->endGroup(); } /************************************************ ************************************************/ void UKUIPanel::saveSettings(bool later) { mDelaySave.stop(); if (later) { mDelaySave.start(); return; } mSettings->beginGroup(mConfigGroup); //Note: save/load of plugin names is completely handled by mPlugins object //mSettings->setValue(CFG_KEY_PLUGINS, mPlugins->pluginNames()); mSettings->setValue(CFG_KEY_LINECNT, mLineCount); mSettings->setValue(CFG_KEY_LENGTH, mLength); mSettings->setValue(CFG_KEY_PERCENT, mLengthInPercents); mSettings->setValue(CFG_KEY_SCREENNUM, mScreenNum); // mSettings->setValue(CFG_KEY_POSITION, positionToStr(mPosition)); mSettings->setValue(CFG_KEY_ALIGNMENT, mAlignment); mSettings->setValue(CFG_KEY_RESERVESPACE, mReserveSpace); mSettings->setValue(CFG_KEY_HIDABLE, mHidable); mSettings->setValue(CFG_KEY_VISIBLE_MARGIN, mVisibleMargin); mSettings->setValue(CFG_KEY_ANIMATION, mAnimationTime); mSettings->setValue(CFG_KEY_SHOW_DELAY, mShowDelayTimer.interval()); mSettings->setValue(CFG_KEY_LOCKPANEL, mLockPanel); mSettings->endGroup(); } /*确保任务栏在调整分辨率和增加·屏幕之后能保持显示正常*/ void UKUIPanel::ensureVisible() { if (!canPlacedOn(mScreenNum, mPosition)) setPosition(findAvailableScreen(mPosition), mPosition, false); else mActualScreenNum = mScreenNum; // the screen size might be changed realign(); } UKUIPanel::~UKUIPanel() { mLayout->setEnabled(false); delete mAnimation; // delete mConfigDialog.data(); // do not save settings because of "user deleted panel" functionality saveSettings(); } void UKUIPanel::show() { QWidget::show(); KWindowSystem::setOnDesktop(effectiveWinId(), NET::OnAllDesktops); } QStringList pluginDesktopDirs() { QStringList dirs; dirs << QString(getenv("UKUI_PANEL_PLUGINS_DIR")).split(':', QString::SkipEmptyParts); dirs << QString("%1/%2").arg(XdgDirs::dataHome(), "/ukui/ukui-panel"); dirs << PLUGIN_DESKTOPS_DIR; return dirs; } /*加载pluginDesktopDirs 获取到的列表中的插件*/ void UKUIPanel::loadPlugins() { QString names_key(mConfigGroup); names_key += '/'; names_key += QLatin1String(CFG_KEY_PLUGINS); mPlugins.reset(new PanelPluginsModel(this, names_key, pluginDesktopDirs())); connect(mPlugins.data(), &PanelPluginsModel::pluginAdded, mLayout, &UKUIPanelLayout::addPlugin); connect(mPlugins.data(), &PanelPluginsModel::pluginMovedUp, mLayout, &UKUIPanelLayout::moveUpPlugin); //reemit signals connect(mPlugins.data(), &PanelPluginsModel::pluginAdded, this, &UKUIPanel::pluginAdded); connect(mPlugins.data(), &PanelPluginsModel::pluginRemoved, this, &UKUIPanel::pluginRemoved); const auto plugins = mPlugins->plugins(); for (auto const & plugin : plugins) { mLayout->addPlugin(plugin); connect(plugin, &Plugin::dragLeft, [this] { mShowDelayTimer.stop(); hidePanel();}); } } void UKUIPanel::reloadPlugins(QString model){ QStringList list=readConfig(model); checkPlugins(list); movePlugins(list); } QStringList UKUIPanel::readConfig(QString model){ QStringList list; mSettings->beginGroup(mConfigGroup); if(model=="pc"){ list = mSettings->value(CFG_KEY_PLUGINS_PC).toStringList(); }else{ list = mSettings->value(CFG_KEY_PLUGINS_PAD).toStringList(); } mSettings->endGroup(); return list; } void UKUIPanel::checkPlugins(QStringList list){ const auto plugins = mPlugins->plugins(); for (auto const & plugin : plugins) { plugin->hide(); } for(int i=0;ipluginNames().contains(list[i])){ if(mPlugins->pluginByName(list[i])){ mPlugins->pluginByName(list[i])->show(); } } } } void UKUIPanel::movePlugins(QStringList list){ for(int i=0;icount();i++){ mLayout->removeItem(mLayout->itemAt(i)); } const auto plugins = mPlugins->plugins(); for (auto const & plugin : plugins) { if(!plugin->isHidden()){ mLayout->addWidget(plugin); } } } int UKUIPanel::getReserveDimension() { return mHidable ? PANEL_HIDE_SIZE : qMax(PANEL_MINIMUM_SIZE, mPanelSize); } /* get primary screen changed in 990*/ void UKUIPanel::priScreenChanged(int x, int y, int width, int height) { mcurrentScreenRect.setRect(x, y, width, height); setPanelGeometry(); realign(); } /* The setting frame of the old panel does not follow the main screen but can be displayed on any screen but the current desktop environment of ukui is set to follow the main screen All default parameters desktop()->screenGeometry are 0 */ void UKUIPanel::setPanelGeometry(bool animate) { QRect currentScreen; QRect rect; currentScreen=QGuiApplication::screens().at(0)->geometry(); if (isHorizontal()){ rect.setHeight(qMax(PANEL_MINIMUM_SIZE, mPanelSize)); if (mLengthInPercents) rect.setWidth(currentScreen.width() * mLength / 100.0); else{ if (mLength <= 0) rect.setWidth(currentScreen.width() + mLength); else rect.setWidth(mLength); } rect.setWidth(qMax(rect.size().width(), mLayout->minimumSize().width())); // Horiz ...................... switch (mAlignment) { case UKUIPanel::AlignmentLeft: rect.moveLeft(currentScreen.left()); break; case UKUIPanel::AlignmentCenter: rect.moveCenter(currentScreen.center()); break; case UKUIPanel::AlignmentRight: rect.moveRight(currentScreen.right()); break; } // Vert ....................... if (mPosition == IUKUIPanel::PositionTop) { if (mHidden) rect.moveBottom(currentScreen.top() + PANEL_HIDE_SIZE); else rect.moveTop(currentScreen.top()); } else { if (mHidden) rect.moveTop(currentScreen.bottom() - PANEL_HIDE_SIZE); else rect.moveBottom(currentScreen.bottom()); } qDebug()<<"ukui-panel Rect is :"<minimumSize().height())); // Vert ....................... switch (mAlignment) { case UKUIPanel::AlignmentLeft: rect.moveTop(currentScreen.top()); break; case UKUIPanel::AlignmentCenter: rect.moveCenter(currentScreen.center()); break; case UKUIPanel::AlignmentRight: rect.moveBottom(currentScreen.bottom()); break; } // Horiz ...................... if (mPosition == IUKUIPanel::PositionLeft) { if (mHidden) rect.moveRight(currentScreen.left() + PANEL_HIDE_SIZE); else rect.moveLeft(currentScreen.left()); } else { if (mHidden) rect.moveLeft(currentScreen.right() - PANEL_HIDE_SIZE); else rect.moveRight(currentScreen.right()); } } if (rect != geometry()) { setFixedSize(rect.size()); if (animate) { if (mAnimation == nullptr) { mAnimation = new QPropertyAnimation(this, "geometry"); mAnimation->setEasingCurve(QEasingCurve::Linear); //Note: for hiding, the margins are set after animation is finished connect(mAnimation, &QAbstractAnimation::finished, [this] { if (mHidden) setMargins(); }); } mAnimation->setDuration(mAnimationTime); mAnimation->setStartValue(geometry()); mAnimation->setEndValue(rect); //Note: for showing-up, the margins are removed instantly if (!mHidden) setMargins(); mAnimation->start(); } else { setMargins(); setGeometry(rect); } } QDBusMessage message =QDBusMessage::createSignal("/panel/position", "org.ukui.panel", "UKuiPanelPosition"); QList args; args.append(currentScreen.x()); args.append(currentScreen.y()); args.append(currentScreen.width()); args.append(currentScreen.height()); args.append(panelSize()); args.append(gsettings->get(PANEL_POSITION_KEY).toInt()); message.setArguments(args); QDBusConnection::sessionBus().send(message); } /*设置边距*/ void UKUIPanel::setMargins() { if (mHidden) { if (isHorizontal()) { if (mPosition == IUKUIPanel::PositionTop) mLayout->setContentsMargins(0, 0, 0, PANEL_HIDE_SIZE); else mLayout->setContentsMargins(0, PANEL_HIDE_SIZE, 0, 0); } else { if (mPosition == IUKUIPanel::PositionLeft) mLayout->setContentsMargins(0, 0, PANEL_HIDE_SIZE, 0); else mLayout->setContentsMargins(PANEL_HIDE_SIZE, 0, 0, 0); } if (!mVisibleMargin) setWindowOpacity(0.0); } else { mLayout->setContentsMargins(0, 0, 0, 0); if (!mVisibleMargin) setWindowOpacity(1.0); } } /* * ukui-panel 的实时调整功能 * QEvent::LayoutRequest 能监听到widget should be relayouted时候的信号 * emit realigned() 信号在PanelPluginsModel类中传给插件的realign函数 * 所有的插件类都需要重写这个函数用以跟任务栏的位置保持一致 * UKUIPanel::event -> UKUIPanel::realign() -> Plugin::realign() ->UKUITrayPlugin:realign */ void UKUIPanel::realign() { emit realigned(); if (!isVisible()) return; #if 0 qDebug() << "** Realign *********************"; qDebug() << "PanelSize: " << mPanelSize; qDebug() << "IconSize: " << mIconSize; qDebug() << "LineCount: " << mLineCount; qDebug() << "Length: " << mLength << (mLengthInPercents ? "%" : "px"); qDebug() << "Alignment: " << (mAlignment == 0 ? "center" : (mAlignment < 0 ? "left" : "right")); qDebug() << "Position: " << positionToStr(mPosition) << "on" << mScreenNum; qDebug() << "Plugins count: " << mPlugins.count(); #endif setPanelGeometry(); // Reserve our space on the screen .......... // It's possible that our geometry is not changed, but screen resolution is changed, // so resetting WM_STRUT is still needed. To make it simple, we always do it. updateWmStrut(); } // Update the _NET_WM_PARTIAL_STRUT and _NET_WM_STRUT properties for the window void UKUIPanel::updateWmStrut() { WId wid = effectiveWinId(); if(wid == 0 || !isVisible()) return; if (mReserveSpace) { const QRect wholeScreen = QApplication::desktop()->geometry(); const QRect rect = geometry(); // NOTE: https://standards.freedesktop.org/wm-spec/wm-spec-latest.html // Quote from the EWMH spec: " Note that the strut is relative to the screen edge, and not the edge of the xinerama monitor." // So, we use the geometry of the whole screen to calculate the strut rather than using the geometry of individual monitors. // Though the spec only mention Xinerama and did not mention XRandR, the rule should still be applied. // At least openbox is implemented like this. switch (mPosition) { case UKUIPanel::PositionTop: KWindowSystem::setExtendedStrut(wid, /* Left */ 0, 0, 0, /* Right */ 0, 0, 0, /* Top */ getReserveDimension(), rect.left(), rect.right(), /* Bottom */ 0, 0, 0 ); break; case UKUIPanel::PositionBottom: KWindowSystem::setExtendedStrut(wid, /* Left */ 0, 0, 0, /* Right */ 0, 0, 0, /* Top */ 0, 0, 0, /* Bottom */ getReserveDimension(), rect.left(), rect.right() ); break; case UKUIPanel::PositionLeft: KWindowSystem::setExtendedStrut(wid, /* Left */ getReserveDimension(), rect.top(), rect.bottom(), /* Right */ 0, 0, 0, /* Top */ 0, 0, 0, /* Bottom */ 0, 0, 0 ); break; case UKUIPanel::PositionRight: KWindowSystem::setExtendedStrut(wid, /* Left */ 0, 0, 0, /* Right */ getReserveDimension(), rect.top(), rect.bottom(), /* Top */ 0, 0, 0, /* Bottom */ 0, 0, 0 ); break; } } else { KWindowSystem::setExtendedStrut(wid, /* Left */ 0, 0, 0, /* Right */ 0, 0, 0, /* Top */ 0, 0, 0, /* Bottom */ 0, 0, 0 ); } } /************************************************ The panel can't be placed on boundary of two displays. This function checks if the panel can be placed on the display @screenNum on @position. ************************************************/ bool UKUIPanel::canPlacedOn(int screenNum, UKUIPanel::Position position) { QDesktopWidget* dw = QApplication::desktop(); switch (position) { case UKUIPanel::PositionTop: for (int i = 0; i < dw->screenCount(); ++i) if (dw->screenGeometry(i).bottom() < dw->screenGeometry(screenNum).top()) return false; return true; case UKUIPanel::PositionBottom: for (int i = 0; i < dw->screenCount(); ++i) if (dw->screenGeometry(i).top() > dw->screenGeometry(screenNum).bottom()) return false; return true; case UKUIPanel::PositionLeft: for (int i = 0; i < dw->screenCount(); ++i) if (dw->screenGeometry(i).right() < dw->screenGeometry(screenNum).left()) return false; return true; case UKUIPanel::PositionRight: for (int i = 0; i < dw->screenCount(); ++i) if (dw->screenGeometry(i).left() > dw->screenGeometry(screenNum).right()) return false; return true; } return false; } /************************************************ ************************************************/ int UKUIPanel::findAvailableScreen(UKUIPanel::Position position) { int current = mScreenNum; for (int i = current; i < QApplication::desktop()->screenCount(); ++i) if (canPlacedOn(i, position)) return i; for (int i = 0; i < current; ++i) if (canPlacedOn(i, position)) return i; return 0; } //void UKUIPanel::showConfigDialog() //{ // if (mConfigDialog.isNull()) // mConfigDialog = new ConfigPanelDialog(this, nullptr /*make it top level window*/); // mConfigDialog->showConfigPanelPage(); // mStandaloneWindows->observeWindow(mConfigDialog.data()); // mConfigDialog->show(); // mConfigDialog->raise(); // mConfigDialog->activateWindow(); // WId wid = mConfigDialog->windowHandle()->winId(); // KWindowSystem::activateWindow(wid); // KWindowSystem::setOnDesktop(wid, KWindowSystem::currentDesktop()); // mConfigDialog = new ConfigPanelDialog(this, nullptr); // mConfigDialog->show(); // //mConfigWidget->positionChanged(); //} /************************************************ ************************************************/ //void UKUIPanel::showAddPluginDialog() //{ // if (mConfigDialog.isNull()) // mConfigDialog = new ConfigPanelDialog(this, nullptr /*make it top level window*/); // mConfigDialog->showConfigPluginsPage(); // mStandaloneWindows->observeWindow(mConfigDialog.data()); // mConfigDialog->show(); // mConfigDialog->raise(); // mConfigDialog->activateWindow(); // WId wid = mConfigDialog->windowHandle()->winId(); // KWindowSystem::activateWindow(wid); // KWindowSystem::setOnDesktop(wid, KWindowSystem::currentDesktop()); //} /*右键 系统监视器选项*/ void UKUIPanel::systeMonitor() { QProcess *process =new QProcess(this); process->startDetached("/usr/bin/ukui-system-monitor"); process->deleteLater(); } /*任务栏大小和方向的调整*/ void UKUIPanel::adjustPanel() { QAction *pmenuaction_s; QAction *pmenuaction_m; QAction *pmenuaction_l; pmenuaction_s=new QAction(this); pmenuaction_s->setText(tr("Small")); pmenuaction_m=new QAction(this); pmenuaction_m->setText(tr("Medium")); pmenuaction_l=new QAction(this); pmenuaction_l->setText(tr("Large")); QMenu *pmenu_panelsize; pmenu_panelsize=new QMenu(this); pmenu_panelsize->setTitle(tr("Adjustment Size")); pmenu_panelsize->addAction(pmenuaction_s); pmenu_panelsize->addAction(pmenuaction_m); pmenu_panelsize->addAction(pmenuaction_l); pmenu_panelsize->setWindowOpacity(0.9); menu->addMenu(pmenu_panelsize); pmenuaction_s->setCheckable(true); pmenuaction_m->setCheckable(true); pmenuaction_l->setCheckable(true); pmenuaction_s->setChecked(gsettings->get(PANEL_SIZE_KEY).toInt()==PANEL_SIZE_SMALL); pmenuaction_m->setChecked(gsettings->get(PANEL_SIZE_KEY).toInt()==PANEL_SIZE_MEDIUM); pmenuaction_l->setChecked(gsettings->get(PANEL_SIZE_KEY).toInt()==PANEL_SIZE_LARGE); connect(pmenuaction_s,&QAction::triggered,[this] { gsettings->set(PANEL_SIZE_KEY,PANEL_SIZE_SMALL); gsettings->set(ICON_SIZE_KEY,ICON_SIZE_SMALL); setIconSize(ICON_SIZE_SMALL,true); }); connect(pmenuaction_m,&QAction::triggered,[this] { gsettings->set(PANEL_SIZE_KEY,PANEL_SIZE_MEDIUM); gsettings->set(ICON_SIZE_KEY,ICON_SIZE_MEDIUM); setIconSize(ICON_SIZE_MEDIUM,true); }); connect(pmenuaction_l,&QAction::triggered,[this] { gsettings->set(PANEL_SIZE_KEY,PANEL_SIZE_LARGE); gsettings->set(ICON_SIZE_KEY,ICON_SIZE_LARGE); setIconSize(ICON_SIZE_LARGE,true); }); pmenu_panelsize->setDisabled(mLockPanel); QAction *pmenuaction_top; QAction *pmenuaction_bottom; QAction *pmenuaction_left; QAction *pmenuaction_right; pmenuaction_top=new QAction(this); pmenuaction_top->setText(tr("Up")); pmenuaction_bottom=new QAction(this); pmenuaction_bottom->setText(tr("Bottom")); pmenuaction_left=new QAction(this); pmenuaction_left->setText(tr("Left")); pmenuaction_right=new QAction(this); pmenuaction_right->setText(tr("Right")); QMenu *pmenu_positon; pmenu_positon=new QMenu(this); pmenu_positon->setTitle(tr("Adjustment Position")); pmenu_positon->addAction(pmenuaction_top); pmenu_positon->addAction(pmenuaction_bottom); pmenu_positon->addAction(pmenuaction_left); pmenu_positon->addAction(pmenuaction_right); menu->addMenu(pmenu_positon); pmenuaction_top->setCheckable(true); pmenuaction_bottom->setCheckable(true); pmenuaction_left->setCheckable(true); pmenuaction_right->setCheckable(true); pmenuaction_top->setChecked(gsettings->get(PANEL_POSITION_KEY).toInt()==1); pmenuaction_bottom->setChecked(gsettings->get(PANEL_POSITION_KEY).toInt()==0); pmenuaction_left->setChecked(gsettings->get(PANEL_POSITION_KEY).toInt()==2); pmenuaction_right->setChecked(gsettings->get(PANEL_POSITION_KEY).toInt()==3); connect(pmenuaction_top,&QAction::triggered, [this] { setPosition(0,PositionTop,true);}); connect(pmenuaction_bottom,&QAction::triggered, [this] { setPosition(0,PositionBottom,true);}); connect(pmenuaction_left,&QAction::triggered, [this] { setPosition(0,PositionLeft,true);}); connect(pmenuaction_right,&QAction::triggered, [this] { setPosition(0,PositionRight,true);}); pmenu_positon->setWindowOpacity(0.9); pmenu_positon->setDisabled(mLockPanel); mSettings->beginGroup(mConfigGroup); QAction * hidepanel = menu->addAction(tr("Hide Panel")); hidepanel->setDisabled(mLockPanel); hidepanel->setCheckable(true); hidepanel->setChecked(mHidable); connect(hidepanel, &QAction::triggered, [this] { mSettings->beginGroup(mConfigGroup); mHidable = mSettings->value(CFG_KEY_HIDABLE, mHidable).toBool(); mSettings->endGroup(); if(mHidable) mHideTimer.stop(); setHidable(!mHidable,true); mHidden=mHidable; mShowDelayTimer.start(); time->start(1000); }); mSettings->endGroup(); } /*右键 显示桌面选项*/ void UKUIPanel::showDesktop() { KWindowSystem::setShowingDesktop(!KWindowSystem::showingDesktop()); } /*右键 显示任务视图 选项*/ void UKUIPanel::showTaskView() { // system("ukui-window-switch --show-workspace"); if(gsettings->keys().contains(SHOW_TASKVIEW)) { if(gsettings->get(SHOW_TASKVIEW).toBool()){ gsettings->set(SHOW_TASKVIEW,false); } else gsettings->set(SHOW_TASKVIEW,true); } } /*右键 显示夜间模式按钮 选项*/ void UKUIPanel::showNightModeButton() { // system("ukui-window-switch --show-workspace"); if(gsettings->keys().contains(SHOW_NIGHTMODE)) { if(gsettings->get(SHOW_NIGHTMODE).toBool()){ gsettings->set(SHOW_NIGHTMODE,false); } else gsettings->set(SHOW_NIGHTMODE,true); } } /*设置任务栏高度*/ void UKUIPanel::setPanelSize(int value, bool save) { if (mPanelSize != value) { mPanelSize = value; realign(); if (save) saveSettings(true); } } /*设置任务栏图标大小*/ void UKUIPanel::setIconSize(int value, bool save) { if (mIconSize != value) { mIconSize = value; mLayout->setLineSize(mIconSize); if (save) saveSettings(true); realign(); } } void UKUIPanel::setLineCount(int value, bool save) { if (mLineCount != value) { mLineCount = value; mLayout->setEnabled(false); mLayout->setLineCount(mLineCount); mLayout->setEnabled(true); if (save) saveSettings(true); realign(); } } /************************************************ ************************************************/ void UKUIPanel::setLength(int length, bool inPercents, bool save) { if (mLength == length && mLengthInPercents == inPercents) return; mLength = length; mLengthInPercents = inPercents; if (save) saveSettings(true); realign(); } /************************************************ ************************************************/ void UKUIPanel::setPosition(int screen, IUKUIPanel::Position position, bool save) { if (mScreenNum == screen && mPosition == position) return; mActualScreenNum = screen; mPosition = position; mLayout->setPosition(mPosition); if (save) { mScreenNum = screen; saveSettings(true); } // Qt 5 adds a new class QScreen and add API for setting the screen of a QWindow. // so we had better use it. However, without this, our program should still work // as long as XRandR is used. Since XRandR combined all screens into a large virtual desktop // every screen and their virtual siblings are actually on the same virtual desktop. // So things still work if we don't set the screen correctly, but this is not the case // for other backends, such as the upcoming wayland support. Hence it's better to set it. if(windowHandle()) { // QScreen* newScreen = qApp->screens().at(screen); // QScreen* oldScreen = windowHandle()->screen(); // const bool shouldRecreate = windowHandle()->handle() && !(oldScreen && oldScreen->virtualSiblings().contains(newScreen)); // Q_ASSERT(shouldRecreate == false); // NOTE: When you move a window to another screen, Qt 5 might recreate the window as needed // But luckily, this never happen in XRandR, so Qt bug #40681 is not triggered here. // (The only exception is when the old screen is destroyed, Qt always re-create the window and // this corner case triggers #40681.) // When using other kind of multihead settings, such as Xinerama, this might be different and // unless Qt developers can fix their bug, we have no way to workaround that. windowHandle()->setScreen(qApp->screens().at(screen)); } realign(); gsettings->set(PANEL_POSITION_KEY,position); setPanelGeometry(true); } /************************************************ * ************************************************/ void UKUIPanel::setAlignment(Alignment value, bool save) { if (mAlignment == value) return; mAlignment = value; if (save) saveSettings(true); realign(); } /************************************************ * ************************************************/ void UKUIPanel::setFontColor(QColor color, bool save) { mFontColor = color; if (save) saveSettings(true); } /************************************************ ************************************************/ void UKUIPanel::setBackgroundColor(QColor color, bool save) { mBackgroundColor = color; if (save) saveSettings(true); } void UKUIPanel::setReserveSpace(bool reserveSpace, bool save) { if (mReserveSpace == reserveSpace) return; mReserveSpace = reserveSpace; if (save) saveSettings(true); updateWmStrut(); } /************************************************ ************************************************/ QRect UKUIPanel::globalGeometry() const { // panel is the the top-most widget/window, no calculation needed return geometry(); } /************************************************ ************************************************/ bool UKUIPanel::event(QEvent *event) { switch (event->type()) { case QEvent::ContextMenu: showPopupMenu(); break; case QEvent::LayoutRequest: emit realigned(); break; case QEvent::WinIdChange: { // qDebug() << "WinIdChange" << hex << effectiveWinId(); if(effectiveWinId() == 0) break; // Sometimes Qt needs to re-create the underlying window of the widget and // the winId() may be changed at runtime. So we need to reset all X11 properties // when this happens. //qDebug() << "WinIdChange" << hex << effectiveWinId() << "handle" << windowHandle() << windowHandle()->screen(); // Qt::WA_X11NetWmWindowTypeDock becomes ineffective in Qt 5 // See QTBUG-39887: https://bugreports.qt-project.org/browse/QTBUG-39887 // Let's use KWindowSystem for that KWindowSystem::setType(effectiveWinId(), NET::Dock); updateWmStrut(); // reserve screen space for the panel KWindowSystem::setOnAllDesktops(effectiveWinId(), true); break; } case QEvent::DragEnter: dynamic_cast(event)->setDropAction(Qt::IgnoreAction); event->accept(); //no break intentionally case QEvent::Enter: // reloadPlugins("pc"); mShowDelayTimer.start(); break; case QEvent::Leave: // reloadPlugins("pad"); case QEvent::DragLeave: mShowDelayTimer.stop(); hidePanel(); break; default: break; } return QFrame::event(event); } /************************************************ ************************************************/ void UKUIPanel::showEvent(QShowEvent *event) { QFrame::showEvent(event); realign(); } void UKUIPanel::styleAdjust() { QString filename = QDir::homePath() + "/.config/ukui/panel-commission.ini"; QSettings m_settings(filename, QSettings::IniFormat); m_settings.setIniCodec("UTF-8"); m_settings.beginGroup("Transparency"); QString transparency_action = m_settings.value("transparency", "").toString(); if (transparency_action.isEmpty()) { transparency_action = "open"; } m_settings.endGroup(); const QByteArray transparency_id(TRANSPARENCY_SETTINGS); if(QGSettings::isSchemaInstalled(transparency_id)){ transparency_gsettings = new QGSettings(transparency_id); transparency=transparency_gsettings->get(TRANSPARENCY_KEY).toDouble()*255; this->update(); connect(transparency_gsettings, &QGSettings::changed, this, [=] (const QString &key){ if(key==TRANSPARENCY_KEY && transparency_action=="open"){ transparency=transparency_gsettings->get(TRANSPARENCY_KEY).toDouble()*255; this->update(); } }); }else{ transparency=0.75; } } /* 使用paintEvent 对panel进行绘制的时候有如下问题: * 1.绘制速度需要鼠标事件触发,明显的切换不流畅 * 2.部分区域绘制不能生效,调整任务栏高度之后才能生效 */ void UKUIPanel::paintEvent(QPaintEvent *) { QStyleOption opt; opt.init(this); QPainter p(this); p.setPen(Qt::NoPen); // p.setBrush(QBrush(QColor(19,22,28,transparency))); QColor color= palette().color(QPalette::Base); color.setAlpha(transparency); QBrush brush = QBrush(color); p.setBrush(brush); p.setRenderHint(QPainter::Antialiasing); p.drawRoundedRect(opt.rect,0,0); style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); } /*Right-Clicked Menu of ukui-panel * it's a Popup Menu */ void UKUIPanel::showPopupMenu(Plugin *plugin) { menu = new QMenu(this); menu->setAttribute(Qt::WA_DeleteOnClose); /* @new features * //Plugin Menu 负责显示插件的菜单项,ukui3.0的设计暂时不需要插件菜单项 * 关于后续的插件右键菜单的详细调整 * 如果需要在任务栏菜单项上面添加 插件的菜单选项就放开此功能 * 放开此功能可以丰富插件右键菜单,windows是这样做的 */ if (plugin) { QMenu *m = plugin->popupMenu(); if (m) { //menu->addTitle(plugin->windowTitle()); const auto actions = m->actions(); for (auto const & action : actions) { action->setParent(menu); action->setDisabled(mLockPanel); menu->addAction(action); } delete m; } } /* // menu->addTitle(QIcon(), tr("Panel")); menu->addAction(XdgIcon::fromTheme(QLatin1String("configure")), tr("Configure Panel"), this, SLOT(showConfigDialog()) )->setDisabled(mLockPanel); menu->addAction(XdgIcon::fromTheme("preferences-plugin"), tr("Manage Widgets"), this, SLOT(showAddPluginDialog()) )->setDisabled(mLockPanel); */ menu->addSeparator(); QAction * showtaskview = menu->addAction(tr("Show Taskview")); showtaskview->setCheckable(true); showtaskview->setChecked(gsettings->get(SHOW_TASKVIEW).toBool()); connect(showtaskview, &QAction::triggered, [this] { showTaskView(); }); QString filename = QDir::homePath() + "/.config/ukui/panel-commission.ini"; QSettings m_settings(filename, QSettings::IniFormat); m_settings.setIniCodec("UTF-8"); m_settings.beginGroup("NightMode"); QString nightmode_action = m_settings.value("nightmode", "").toString(); if (nightmode_action.isEmpty()) { nightmode_action = "show"; } m_settings.endGroup(); if(nightmode_action == "show"){ QAction * shownightmode = menu->addAction(tr("Show Nightmode")); shownightmode->setCheckable(true); shownightmode->setChecked(gsettings->get(SHOW_NIGHTMODE).toBool()); connect(shownightmode, &QAction::triggered, [this] { showNightModeButton(); }); } menu->addAction(XdgIcon::fromTheme(QLatin1String("configure")), tr("Show Desktop"), this, SLOT(showDesktop()) ); menu->addSeparator(); if(QFileInfo::exists(QString("/usr/bin/ukui-system-monitor"))){ menu->addAction(XdgIcon::fromTheme(QLatin1String("configure")), tr("Show System Monitor"), this, SLOT(systeMonitor()) ); } menu->addSeparator(); adjustPanel(); /* UKUIPanelApplication *a = reinterpret_cast(qApp); menu->addAction(XdgIcon::fromTheme(QLatin1String("list-add")), tr("Add New Panel"), a, SLOT(addNewPanel()) ); if (a->count() > 1) { menu->addAction(XdgIcon::fromTheme(QLatin1String("list-remove")), tr("Remove Panel", "Menu Item"), this, SLOT(userRequestForDeletion()) )->setDisabled(mLockPanel); } */ m_lockAction = menu->addAction(tr("Lock This Panel")); m_lockAction->setCheckable(true); m_lockAction->setChecked(mLockPanel); connect(m_lockAction, &QAction::triggered, [this] { mLockPanel = !mLockPanel; saveSettings(false); }); //Hidden features, lock the panel /* menu->addAction(XdgIcon::fromTheme(QLatin1String("configure")), tr("Reset Panel"), this, SLOT(panelReset()) )->setDisabled(mLockPanel); */ QAction *about; about=new QAction(this); about->setText(tr("About Kylin")); menu->addAction(about); connect(about,&QAction::triggered, [this] { QProcess *process =new QProcess(this); process->start( "bash", QStringList() << "-c" << "dpkg -l | grep ukui-control-center"); process->waitForFinished(); QString strResult = process->readAllStandardOutput() + process->readAllStandardError(); if (-1 != strResult.indexOf("3.0")) { QProcess::startDetached(QString("ukui-control-center -a")); } else { QProcess::startDetached(QString("ukui-control-center -m About")); } }); #ifdef DEBUG menu->addSeparator(); menu->addAction("Exit (debug only)", qApp, SLOT(quit())); #endif /* Note: in multihead & multipanel setup the QMenu::popup/exec places the window * sometimes wrongly (it seems that this bug is somehow connected to misinterpretation * of QDesktopWidget::availableGeometry) */ menu->setGeometry(calculatePopupWindowPos(QCursor::pos(), menu->sizeHint())); willShowWindow(menu); menu->show(); } Plugin* UKUIPanel::findPlugin(const IUKUIPanelPlugin* iPlugin) const { const auto plugins = mPlugins->plugins(); for (auto const & plug : plugins) if (plug->iPlugin() == iPlugin) return plug; return nullptr; } /************************************************ ************************************************/ QRect UKUIPanel::calculatePopupWindowPos(QPoint const & absolutePos, QSize const & windowSize) const { int x = absolutePos.x(), y = absolutePos.y(); switch (position()) { case IUKUIPanel::PositionTop: y = globalGeometry().bottom(); break; case IUKUIPanel::PositionBottom: y = globalGeometry().top() - windowSize.height(); break; case IUKUIPanel::PositionLeft: x = globalGeometry().right(); break; case IUKUIPanel::PositionRight: x = globalGeometry().left() - windowSize.width(); break; } QRect res(QPoint(x, y), windowSize); QRect screen = QApplication::desktop()->screenGeometry(this); // NOTE: We cannot use AvailableGeometry() which returns the work area here because when in a // multihead setup with different resolutions. In this case, the size of the work area is limited // by the smallest monitor and may be much smaller than the current screen and we will place the // menu at the wrong place. This is very bad for UX. So let's use the full size of the screen. if (res.right() > screen.right()) res.moveRight(screen.right()); if (res.bottom() > screen.bottom()) res.moveBottom(screen.bottom()); if (res.left() < screen.left()) res.moveLeft(screen.left()); if (res.top() < screen.top()) res.moveTop(screen.top()); return res; } /************************************************ ************************************************/ QRect UKUIPanel::calculatePopupWindowPos(const IUKUIPanelPlugin *plugin, const QSize &windowSize) const { Plugin *panel_plugin = findPlugin(plugin); if (nullptr == panel_plugin) { qWarning() << Q_FUNC_INFO << "Wrong logic? Unable to find Plugin* for" << plugin << "known plugins follow..."; const auto plugins = mPlugins->plugins(); for (auto const & plug : plugins) qWarning() << plug->iPlugin() << plug; return QRect(); } // Note: assuming there are not contentMargins around the "BackgroundWidget" (UKUIPanelWidget) return calculatePopupWindowPos(globalGeometry().topLeft() + panel_plugin->geometry().topLeft(), windowSize); } /************************************************ ************************************************/ void UKUIPanel::willShowWindow(QWidget * w) { mStandaloneWindows->observeWindow(w); } /************************************************ ************************************************/ void UKUIPanel::pluginFlagsChanged(const IUKUIPanelPlugin * /*plugin*/) { mLayout->rebuild(); } /************************************************ ************************************************/ QString UKUIPanel::qssPosition() const { return positionToStr(position()); } /************************************************ ************************************************/ void UKUIPanel::pluginMoved(Plugin * plug) { //get new position of the moved plugin bool found{false}; QString plug_is_before; for (int i=0; icount(); ++i) { Plugin *plugin = qobject_cast(mLayout->itemAt(i)->widget()); if (plugin) { if (found) { //we found our plugin in previous cycle -> is before this (or empty as last) plug_is_before = plugin->settingsGroup(); break; } else found = (plug == plugin); } } mPlugins->movePlugin(plug, plug_is_before); } /************************************************ ************************************************/ void UKUIPanel::userRequestForDeletion() { const QMessageBox::StandardButton ret = QMessageBox::warning(this, tr("Remove Panel", "Dialog Title") , tr("Removing a panel can not be undone.\nDo you want to remove this panel?"), QMessageBox::Yes | QMessageBox::No); if (ret != QMessageBox::Yes) { return; } mSettings->beginGroup(mConfigGroup); const QStringList plugins = mSettings->value("plugins").toStringList(); mSettings->endGroup(); for(const QString& i : plugins) if (!i.isEmpty()) mSettings->remove(i); mSettings->remove(mConfigGroup); emit deletedByUser(this); } void UKUIPanel::showPanel(bool animate) { if (mHidable) { mHideTimer.stop(); if (mHidden) { mHidden = false; setPanelGeometry(mAnimationTime > 0 && animate); } } } void UKUIPanel::hidePanel() { if (mHidable && !mHidden && !mStandaloneWindows->isAnyWindowShown() ) mHideTimer.start(); } void UKUIPanel::hidePanelWork() { if (!geometry().contains(QCursor::pos())) { if (!mStandaloneWindows->isAnyWindowShown()) { mHidden = true; setPanelGeometry(mAnimationTime > 0); } else { mHideTimer.start(); } } QDBusMessage message =QDBusMessage::createSignal("/panel", "org.ukui.panel.settings", "PanelHided"); QDBusConnection::sessionBus().send(message); } void UKUIPanel::setHidable(bool hidable, bool save) { if (mHidable == hidable) return; mHidable = hidable; if (save) saveSettings(true); realign(); } void UKUIPanel::setVisibleMargin(bool visibleMargin, bool save) { if (mVisibleMargin == visibleMargin) return; mVisibleMargin = visibleMargin; if (save) saveSettings(true); realign(); } void UKUIPanel::setAnimationTime(int animationTime, bool save) { if (mAnimationTime == animationTime) return; mAnimationTime = animationTime; if (save) saveSettings(true); } void UKUIPanel::setShowDelay(int showDelay, bool save) { if (mShowDelayTimer.interval() == showDelay) return; mShowDelayTimer.setInterval(showDelay); if (save) saveSettings(true); } QString UKUIPanel::iconTheme() const { return mSettings->value("iconTheme").toString(); } void UKUIPanel::setIconTheme(const QString& iconTheme) { UKUIPanelApplication *a = reinterpret_cast(qApp); a->setIconTheme(iconTheme); } //void UKUIPanel::updateConfigDialog() const //{ // if (!mConfigDialog.isNull() && mConfigDialog->isVisible()) // { // mConfigDialog->updateIconThemeSettings(); // const QList widgets = mConfigDialog->findChildren(); // for (QWidget *widget : widgets) // widget->update(); // } //} bool UKUIPanel::isPluginSingletonAndRunnig(QString const & pluginId) const { Plugin const * plugin = mPlugins->pluginByID(pluginId); if (nullptr == plugin) return false; else return plugin->iPlugin()->flags().testFlag(IUKUIPanelPlugin::SingleInstance); } void UKUIPanel::panelReset() { QFile::remove(QString(qgetenv("HOME"))+"/.config/ukui/panel.conf"); QFile::copy("/usr/share/ukui/panel.conf",QString(qgetenv("HOME"))+"/.config/ukui/panel.conf"); } void UKUIPanel::connectToServer(){ m_cloudInterface = new QDBusInterface("org.kylinssoclient.dbus", "/org/kylinssoclient/path", "org.freedesktop.kylinssoclient.interface", QDBusConnection::sessionBus()); if (!m_cloudInterface->isValid()) { qDebug() << "fail to connect to service"; qDebug() << qPrintable(QDBusConnection::systemBus().lastError().message()); return; } // QDBusConnection::sessionBus().connect(cloudInterface, SIGNAL(shortcutChanged()), this, SLOT(shortcutChangedSlot())); QDBusConnection::sessionBus().connect(QString(), QString("/org/kylinssoclient/path"), QString("org.freedesktop.kylinssoclient.interface"), "keyChanged", this, SLOT(keyChangedSlot(QString))); // 将以后所有DBus调用的超时设置为 milliseconds m_cloudInterface->setTimeout(2147483647); // -1 为默认的25s超时 } void UKUIPanel::keyChangedSlot(const QString &key) { if(key == "ukui-panel") { mSettings->beginGroup(mConfigGroup); mSettings->sync(); mLockPanel = mSettings->value(CFG_KEY_LOCKPANEL).toBool(); mSettings->endGroup(); // if(m_lockAction!=nullptr) // m_lockAction->setChecked(mLockPanel); } } ///////////////////////////////////////////////////////////////////////////////// /// \brief UKUIPanel::areaDivid /// \param globalpos /// \return /// 以下所有函数均为任务栏拖拽相关(位置、大小) ///////////////////////////////////////////////////////////////////////////////// IUKUIPanel::Position UKUIPanel::areaDivid(QPoint globalpos) { int x = globalpos.rx(); int y = globalpos.ry(); float W = QApplication::screens().at(0)->size().width(); float H = QApplication::screens().at(0)->size().height(); float slope = H / W; if ((x < 100 || x > W - 100) && (y > H - 100 || y < 100)) return mPosition; if (y > (int)(x * slope) && y > (int)(H - x * slope)) return PositionBottom; if (y > (int)(x * slope) && y < (int)(H - x * slope)) return PositionLeft; if (y < (int)(x * slope) && y < (int)(H - x * slope)) return PositionTop; if (y < (int)(x * slope) && y > (int)(H - x * slope)) return PositionRight; } void UKUIPanel::mousePressEvent(QMouseEvent *event) { setCursor(Qt::DragMoveCursor); } void UKUIPanel::enterEvent(QEvent *event) { // setCursor(Qt::SizeVerCursor); } void UKUIPanel::leaveEvent(QEvent *event) { setCursor(Qt::ArrowCursor); } void UKUIPanel::mouseMoveEvent(QMouseEvent* event) { if (mLockPanel) return; if (movelock == -1) { if (event->pos().ry() < 10) movelock = 0; else movelock = 1; } if (!movelock) { int panel_h = QApplication::screens().at(0)->size().height() - event->globalPos().ry(); int icon_size = panel_h*0.695652174; setCursor(Qt::SizeVerCursor); if (panel_h <= PANEL_SIZE_LARGE && panel_h >= PANEL_SIZE_SMALL) { setPanelSize(panel_h, true); setIconSize(icon_size, true); gsettings->set(PANEL_SIZE_KEY, panel_h); gsettings->set(ICON_SIZE_KEY, icon_size); } return; } setCursor(Qt::SizeAllCursor); IUKUIPanel::Position currentpos = areaDivid(event->globalPos()); if (oldpos != currentpos) { setPosition(0,currentpos,true); oldpos = currentpos; } } void UKUIPanel::mouseReleaseEvent(QMouseEvent* event) { setCursor(Qt::ArrowCursor); realign(); emit realigned(); movelock = -1; } ukui-panel-3.0.6.4/panel/pluginsettings_p.h0000644000175000017500000000236714203402514017225 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2015 LXQt team * Authors: * Paulo Lieuthier * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef PLUGIN_SETTINGS_P_H #define PLUGIN_SETTINGS_P_H #include "pluginsettings.h" class PluginSettingsFactory { public: static PluginSettings * create(UKUi::Settings *settings, const QString &group, QObject *parent = nullptr); }; #endif //PLUGIN_SETTINGS_P_H ukui-panel-3.0.6.4/panel/pluginsettings.h0000644000175000017500000000515014203402514016677 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2015 LXQt team * Authors: * Paulo Lieuthier * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef PLUGIN_SETTINGS_H #define PLUGIN_SETTINGS_H #include #include #include #include "ukuipanelglobals.h" namespace UKUi { class Settings; } class PluginSettingsFactory; class PluginSettingsPrivate; /*! * \brief * Settings for particular plugin. This object/class can be used similarly as \sa QSettings. * Object cannot be constructed direcly (it is the panel's responsibility to construct it for each plugin). * * * \note * We are relying here on so called "back linking" (calling a function defined in executable * back from an external library)... */ class UKUI_PANEL_API PluginSettings : public QObject { Q_OBJECT //for instantiation friend class PluginSettingsFactory; public: ~PluginSettings(); QString group() const; QVariant value(const QString &key, const QVariant &defaultValue = QVariant()) const; void setValue(const QString &key, const QVariant &value); void remove(const QString &key); bool contains(const QString &key) const; QList > readArray(const QString &prefix); void setArray(const QString &prefix, const QList > &hashList); void clear(); void sync(); QStringList allKeys() const; QStringList childGroups() const; void beginGroup(const QString &subGroup); void endGroup(); void loadFromCache(); Q_SIGNALS: void settingsChanged(); private: explicit PluginSettings(UKUi::Settings *settings, const QString &group, QObject *parent = nullptr); private: QScopedPointer d_ptr; Q_DECLARE_PRIVATE(PluginSettings) }; #endif ukui-panel-3.0.6.4/panel/ukuipanellimits.h0000644000175000017500000000267714203402514017052 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2012 Razor team * Authors: * Luís Pereira * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef UKUIPANELLIMITS_H #define UKUIPANELLIMITS_H #define PANEL_DEFAULT_SIZE 32 #define PANEL_MINIMUM_SIZE 16 #define PANEL_MAXIMUM_SIZE 200 #define PANEL_HIDE_SIZE 4 #define PANEL_DEFAULT_ICON_SIZE 22 #define PANEL_DEFAULT_LINE_COUNT 1 #define PANEL_DEFAULT_BACKGROUND_COLOR "#CCCCCC" #define PANEL_HIDE_DELAY 500 #define PANEL_HIDE_FIRST_TIME (5000 - PANEL_HIDE_DELAY) #define PANEL_SHOW_DELAY 0 #define SETTINGS_SAVE_DELAY 1000 #endif // UKUIPANELLIMITS_H ukui-panel-3.0.6.4/panel/common/0000755000175000017500000000000014203402514014736 5ustar fengfengukui-panel-3.0.6.4/panel/common/ukuigridlayout.h0000644000175000017500000001440314203402514020172 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2012 Razor team * Authors: * Alexander Sokoloff * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef UKUIGRIDLAYOUT_H #define UKUIGRIDLAYOUT_H #include #include "ukuiglobals.h" #include namespace UKUi { class GridLayoutPrivate; /** The GridLayout class lays out widgets in a grid. **/ class UKUI_API GridLayout: public QLayout { Q_OBJECT public: /** This enum type is used to describe direction for this grid. **/ enum Direction { LeftToRight, ///< The items are first laid out horizontally and then vertically. TopToBottom ///< The items are first laid out vertically and then horizontally. }; /** This enum type is used to describe stretch. It contains one horizontal and one vertical flags that can be combined to produce the required effect. */ enum StretchFlag { NoStretch = 0, ///< No justifies items StretchHorizontal = 1, ///< Justifies items in the available horizontal space StretchVertical = 2 ///< Justifies items in the available vertical space }; Q_DECLARE_FLAGS(Stretch, StretchFlag) /** Constructs a new GridLayout with parent widget, parent. The layout has one row and zero column initially, and will expand to left when new items are inserted. **/ explicit GridLayout(QWidget *parent = 0); /** Destroys the grid layout. The layout's widgets aren't destroyed. **/ ~GridLayout(); void addItem(QLayoutItem *item); QLayoutItem *itemAt(int index) const; QLayoutItem *takeAt(int index); int count() const; void invalidate(); QSize sizeHint() const; void setGeometry(const QRect &geometry); QRect occupiedGeometry() const; /** Returns the number of rows in this grid. **/ int rowCount() const; /** Sets the number of rows in this grid. If value is 0, then rows count will calculated automatically when new items are inserted. In the most cases you should to set fixed number for one thing, or for rows, or for columns. \sa GridLayout::setColumnCount **/ void setRowCount(int value); /** Returns the number of columns in this grid. **/ int columnCount() const; /** Sets the number of columns in this grid. If value is 0, then columns count will calculated automatically when new items are inserted. In the most cases you should to set fixed number for one thing, or for rows, or for columns. \sa GridLayout::setRowCount **/ void setColumnCount(int value); /** Returns the alignment of this grid. \sa GridLayout::Direction **/ Direction direction() const; /** Sets the direction for this grid. \sa GridLayout::Direction **/ void setDirection(Direction value); /** Returns the stretch flags of this grid. \sa GridLayout::StretchFlag **/ Stretch stretch() const; /** Sets the stretch flags for this grid. \sa GridLayout::StretchFlag **/ void setStretch(Stretch value); /** Moves the item at index position \param from to index position \param to. If \param withAnimation set the reordering will be animated **/ void moveItem(int from, int to, bool withAnimation = false); /** Checks if layout is currently animated after the \sa moveItem() invocation. **/ bool animatedMoveInProgress() const; /** Returns the cells' minimum size. By default, this property contains a size with zero width and height. **/ QSize cellMinimumSize() const; /** Sets the minimum size of all cells to minSize pixels. **/ void setCellMinimumSize(QSize minSize); /** Sets the minimum height of the cells to value without changing the width. Provided for convenience. **/ void setCellMinimumHeight(int value); /** Sets the minimum width of the cells to value without changing the heights. Provided for convenience. **/ void setCellMinimumWidth(int value); /** Returns the cells' maximum size. By default, this property contains a size with zero width and height. **/ QSize cellMaximumSize() const; /** Sets the maximum size of all cells to maxSize pixels. **/ void setCellMaximumSize(QSize maxSize); /** Sets the maximum height of the cells to value without changing the width. Provided for convenience. **/ void setCellMaximumHeight(int value); /** Sets the maximum width of the cells to value without changing the heights. Provided for convenience. **/ void setCellMaximumWidth(int value); /** Sets both the minimum and maximum sizes of the cells to size, thereby preventing it from ever growing or shrinking. **/ void setCellFixedSize(QSize size); /** Sets both the minimum and maximum height of the cells to value without changing the width. Provided for convenience. **/ void setCellFixedHeight(int value); /** Sets both the minimum and maximum width of the cells to value without changing the heights. Provided for convenience. **/ void setCellFixedWidth(int value); private: GridLayoutPrivate* const d_ptr; Q_DECLARE_PRIVATE(GridLayout) }; Q_DECLARE_OPERATORS_FOR_FLAGS(GridLayout::Stretch) } // namespace UKUi #endif // UKUIGRIDLAYOUT_H ukui-panel-3.0.6.4/panel/common/ukuigridlayout.cpp0000644000175000017500000004424014203402514020527 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2012 Razor team * Authors: * Alexander Sokoloff * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "ukuigridlayout.h" #include #include #include #include using namespace UKUi; class UKUi::GridLayoutPrivate { public: GridLayoutPrivate(); ~GridLayoutPrivate(); QList mItems; int mRowCount; int mColumnCount; GridLayout::Direction mDirection; bool mIsValid; QSize mCellSizeHint; QSize mCellMaxSize; int mVisibleCount; GridLayout::Stretch mStretch; bool mAnimate; int mAnimatedItems; //!< counter of currently animated items void updateCache(); int rows() const; int cols() const; void setItemGeometry(QLayoutItem * item, QRect const & geometry); QSize mPrefCellMinSize; QSize mPrefCellMaxSize; QRect mOccupiedGeometry; }; namespace { class ItemMoveAnimation : public QVariantAnimation { public: static void animate(QLayoutItem * item, QRect const & geometry, UKUi::GridLayoutPrivate * layout) { ItemMoveAnimation* animation = new ItemMoveAnimation(item); animation->setStartValue(item->geometry()); animation->setEndValue(geometry); ++layout->mAnimatedItems; connect(animation, &QAbstractAnimation::finished, [layout] { --layout->mAnimatedItems; Q_ASSERT(0 <= layout->mAnimatedItems); }); animation->start(DeleteWhenStopped); } ItemMoveAnimation(QLayoutItem *item) : mItem(item) { setDuration(150); } void updateCurrentValue(const QVariant ¤t) { mItem->setGeometry(current.toRect()); } private: QLayoutItem* mItem; }; } /************************************************ ************************************************/ GridLayoutPrivate::GridLayoutPrivate() { mColumnCount = 0; mRowCount = 0; mDirection = GridLayout::LeftToRight; mIsValid = false; mVisibleCount = 0; mStretch = GridLayout::StretchHorizontal | GridLayout::StretchVertical; mAnimate = false; mAnimatedItems = 0; mPrefCellMinSize = QSize(0,0); mPrefCellMaxSize = QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); } /************************************************ ************************************************/ GridLayoutPrivate::~GridLayoutPrivate() { qDeleteAll(mItems); } /************************************************ ************************************************/ void GridLayoutPrivate::updateCache() { mCellSizeHint = QSize(0, 0); mCellMaxSize = QSize(0, 0); mVisibleCount = 0; const int N = mItems.count(); for (int i=0; i < N; ++i) { QLayoutItem *item = mItems.at(i); if (!item->widget() || item->widget()->isHidden()) continue; int h = qBound(item->minimumSize().height(), item->sizeHint().height(), item->maximumSize().height()); int w = qBound(item->minimumSize().width(), item->sizeHint().width(), item->maximumSize().width()); mCellSizeHint.rheight() = qMax(mCellSizeHint.height(), h); mCellSizeHint.rwidth() = qMax(mCellSizeHint.width(), w); mCellMaxSize.rheight() = qMax(mCellMaxSize.height(), item->maximumSize().height()); mCellMaxSize.rwidth() = qMax(mCellMaxSize.width(), item->maximumSize().width()); mVisibleCount++; #if 0 qDebug() << "-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-"; qDebug() << "item.min" << item->minimumSize().width(); qDebug() << "item.sz " << item->sizeHint().width(); qDebug() << "item.max" << item->maximumSize().width(); qDebug() << "w h" << w << h; qDebug() << "wid.sizeHint" << item->widget()->sizeHint(); qDebug() << "mCellSizeHint:" << mCellSizeHint; qDebug() << "mCellMaxSize: " << mCellMaxSize; qDebug() << "-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-"; #endif } mCellSizeHint.rwidth() = qBound(mPrefCellMinSize.width(), mCellSizeHint.width(), mPrefCellMaxSize.width()); mCellSizeHint.rheight()= qBound(mPrefCellMinSize.height(), mCellSizeHint.height(), mPrefCellMaxSize.height()); mIsValid = !mCellSizeHint.isEmpty(); } /************************************************ ************************************************/ int GridLayoutPrivate::rows() const { if (mRowCount) return mRowCount; if (!mColumnCount) return 1; return ceil(mVisibleCount * 1.0 / mColumnCount); } /************************************************ ************************************************/ int GridLayoutPrivate::cols() const { if (mColumnCount) return mColumnCount; int rows = mRowCount; if (!rows) rows = 1; return ceil(mVisibleCount * 1.0 / rows); } void GridLayoutPrivate::setItemGeometry(QLayoutItem * item, QRect const & geometry) { mOccupiedGeometry |= geometry; if (mAnimate) { ItemMoveAnimation::animate(item, geometry, this); } else { item->setGeometry(geometry); } } /************************************************ ************************************************/ GridLayout::GridLayout(QWidget *parent): QLayout(parent), d_ptr(new GridLayoutPrivate()) { } /************************************************ ************************************************/ GridLayout::~GridLayout() { delete d_ptr; } /************************************************ ************************************************/ void GridLayout::addItem(QLayoutItem *item) { d_ptr->mItems.append(item); } /************************************************ ************************************************/ QLayoutItem *GridLayout::itemAt(int index) const { Q_D(const GridLayout); if (index < 0 || index >= d->mItems.count()) return 0; return d->mItems.at(index); } /************************************************ ************************************************/ QLayoutItem *GridLayout::takeAt(int index) { Q_D(GridLayout); if (index < 0 || index >= d->mItems.count()) return 0; QLayoutItem *item = d->mItems.takeAt(index); return item; } /************************************************ ************************************************/ int GridLayout::count() const { Q_D(const GridLayout); return d->mItems.count(); } /************************************************ ************************************************/ void GridLayout::invalidate() { Q_D(GridLayout); d->mIsValid = false; QLayout::invalidate(); } /************************************************ ************************************************/ int GridLayout::rowCount() const { Q_D(const GridLayout); return d->mRowCount; } /************************************************ ************************************************/ void GridLayout::setRowCount(int value) { Q_D(GridLayout); if (d->mRowCount != value) { d->mRowCount = value; invalidate(); } } /************************************************ ************************************************/ int GridLayout::columnCount() const { Q_D(const GridLayout); return d->mColumnCount; } /************************************************ ************************************************/ void GridLayout::setColumnCount(int value) { Q_D(GridLayout); if (d->mColumnCount != value) { d->mColumnCount = value; invalidate(); } } /************************************************ ************************************************/ GridLayout::Direction GridLayout::direction() const { Q_D(const GridLayout); return d->mDirection; } /************************************************ ************************************************/ void GridLayout::setDirection(GridLayout::Direction value) { Q_D(GridLayout); if (d->mDirection != value) { d->mDirection = value; invalidate(); } } /************************************************ ************************************************/ GridLayout::Stretch GridLayout::stretch() const { Q_D(const GridLayout); return d->mStretch; } /************************************************ ************************************************/ void GridLayout::setStretch(Stretch value) { Q_D(GridLayout); if (d->mStretch != value) { d->mStretch = value; invalidate(); } } /************************************************ ************************************************/ void GridLayout::moveItem(int from, int to, bool withAnimation /*= false*/) { Q_D(GridLayout); d->mAnimate = withAnimation; d->mItems.move(from, to); invalidate(); } /************************************************ ************************************************/ bool GridLayout::animatedMoveInProgress() const { Q_D(const GridLayout); return 0 < d->mAnimatedItems; } /************************************************ ************************************************/ QSize GridLayout::cellMinimumSize() const { Q_D(const GridLayout); return d->mPrefCellMinSize; } /************************************************ ************************************************/ void GridLayout::setCellMinimumSize(QSize minSize) { Q_D(GridLayout); if (d->mPrefCellMinSize != minSize) { d->mPrefCellMinSize = minSize; invalidate(); } } /************************************************ ************************************************/ void GridLayout::setCellMinimumHeight(int value) { Q_D(GridLayout); if (d->mPrefCellMinSize.height() != value) { d->mPrefCellMinSize.setHeight(value); invalidate(); } } /************************************************ ************************************************/ void GridLayout::setCellMinimumWidth(int value) { Q_D(GridLayout); if (d->mPrefCellMinSize.width() != value) { d->mPrefCellMinSize.setWidth(value); invalidate(); } } /************************************************ ************************************************/ QSize GridLayout::cellMaximumSize() const { Q_D(const GridLayout); return d->mPrefCellMaxSize; } /************************************************ ************************************************/ void GridLayout::setCellMaximumSize(QSize maxSize) { Q_D(GridLayout); if (d->mPrefCellMaxSize != maxSize) { d->mPrefCellMaxSize = maxSize; invalidate(); } } /************************************************ ************************************************/ void GridLayout::setCellMaximumHeight(int value) { Q_D(GridLayout); if (d->mPrefCellMaxSize.height() != value) { d->mPrefCellMaxSize.setHeight(value); invalidate(); } } /************************************************ ************************************************/ void GridLayout::setCellMaximumWidth(int value) { Q_D(GridLayout); if (d->mPrefCellMaxSize.width() != value) { d->mPrefCellMaxSize.setWidth(value); invalidate(); } } /************************************************ ************************************************/ void GridLayout::setCellFixedSize(QSize size) { Q_D(GridLayout); if (d->mPrefCellMinSize != size || d->mPrefCellMaxSize != size) { d->mPrefCellMinSize = size; d->mPrefCellMaxSize = size; invalidate(); } } /************************************************ ************************************************/ void GridLayout::setCellFixedHeight(int value) { Q_D(GridLayout); if (d->mPrefCellMinSize.height() != value || d->mPrefCellMaxSize.height() != value) { d->mPrefCellMinSize.setHeight(value); d->mPrefCellMaxSize.setHeight(value); invalidate(); } } /************************************************ ************************************************/ void GridLayout::setCellFixedWidth(int value) { Q_D(GridLayout); if (d->mPrefCellMinSize.width() != value || d->mPrefCellMaxSize.width() != value) { d->mPrefCellMinSize.setWidth(value); d->mPrefCellMaxSize.setWidth(value); invalidate(); } } /************************************************ ************************************************/ QSize GridLayout::sizeHint() const { Q_D(const GridLayout); if (!d->mIsValid) const_cast(d)->updateCache(); return QSize(d->cols() * d->mCellSizeHint.width(), d->rows() * d->mCellSizeHint.height()); } /************************************************ ************************************************/ void GridLayout::setGeometry(const QRect &geometry) { Q_D(GridLayout); const bool visual_h_reversed = parentWidget() && parentWidget()->isRightToLeft(); QLayout::setGeometry(geometry); const QPoint occupied_start = visual_h_reversed ? geometry.topRight() : geometry.topLeft(); d->mOccupiedGeometry.setTopLeft(occupied_start); d->mOccupiedGeometry.setBottomRight(occupied_start); if (!d->mIsValid) d->updateCache(); int y = geometry.top(); int x = geometry.left(); // For historical reasons QRect::right returns left() + width() - 1 // and QRect::bottom() returns top() + height() - 1; // So we use left() + height() and top() + height() // // http://qt-project.org/doc/qt-4.8/qrect.html const int maxX = geometry.left() + geometry.width(); const int maxY = geometry.top() + geometry.height(); const bool stretch_h = d->mStretch.testFlag(StretchHorizontal); const bool stretch_v = d->mStretch.testFlag(StretchVertical); const int cols = d->cols(); int itemWidth = 0; if (stretch_h && 0 < cols) itemWidth = qMin(geometry.width() / cols, d->mCellMaxSize.width()); else itemWidth = d->mCellSizeHint.width(); itemWidth = qBound(qMin(d->mPrefCellMinSize.width(), maxX), itemWidth, d->mPrefCellMaxSize.width()); const int widthRemain = stretch_h && 0 < itemWidth ? geometry.width() % itemWidth : 0; const int rows = d->rows(); int itemHeight = 0; if (stretch_v && 0 < rows) itemHeight = qMin(geometry.height() / rows, d->mCellMaxSize.height()); else itemHeight = d->mCellSizeHint.height(); itemHeight = qBound(qMin(d->mPrefCellMinSize.height(), maxY), itemHeight, d->mPrefCellMaxSize.height()); const int heightRemain = stretch_v && 0 < itemHeight ? geometry.height() % itemHeight : 0; #if 0 qDebug() << "** GridLayout::setGeometry *******************************"; qDebug() << "Geometry:" << geometry; qDebug() << "CellSize:" << d->mCellSizeHint; qDebug() << "Constraints:" << "min" << d->mPrefCellMinSize << "max" << d->mPrefCellMaxSize; qDebug() << "Count" << count(); qDebug() << "Cols:" << d->cols() << "(" << d->mColumnCount << ")"; qDebug() << "Rows:" << d->rows() << "(" << d->mRowCount << ")"; qDebug() << "Stretch:" << "h:" << (d->mStretch.testFlag(StretchHorizontal)) << " v:" << (d->mStretch.testFlag(StretchVertical)); qDebug() << "Item:" << "h:" << itemHeight << " w:" << itemWidth; #endif int remain_height = heightRemain; int remain_width = widthRemain; if (d->mDirection == LeftToRight) { int height = itemHeight + (0 < remain_height-- ? 1 : 0); #if (QT_VERSION < QT_VERSION_CHECK(5,7,0)) for(int i=0;imItems.size();i++){ QLayoutItem *item=d->mItems[i]; #endif #if (QT_VERSION >= QT_VERSION_CHECK(5,7,0)) for (QLayoutItem *item : qAsConst(d->mItems)){ #endif if (!item->widget() || item->widget()->isHidden()) continue; int width = itemWidth + (0 < remain_width-- ? 1 : 0); if (x + width > maxX) { x = geometry.left(); y += height; height = itemHeight + (0 < remain_height-- ? 1 : 0); remain_width = widthRemain; } const int left = visual_h_reversed ? geometry.left() + geometry.right() - x - width + 1 : x; d->setItemGeometry(item, QRect(left, y, width, height)); x += width; } } else { int width = itemWidth + (0 < remain_width-- ? 1 : 0); #if (QT_VERSION < QT_VERSION_CHECK(5,7,0)) for(int i=0;imItems.size();i++) { QLayoutItem *item=d->mItems[i]; #endif #if (QT_VERSION >= QT_VERSION_CHECK(5,7,0)) for (QLayoutItem *item : qAsConst(d->mItems)) { #endif if (!item->widget() || item->widget()->isHidden()) continue; int height = itemHeight + (0 < remain_height-- ? 1 : 0); if (y + height > maxY) { y = geometry.top(); x += width; width = itemWidth + (0 < remain_width-- ? 1 : 0); remain_height = heightRemain; } const int left = visual_h_reversed ? geometry.left() + geometry.right() - x - width + 1 : x; d->setItemGeometry(item, QRect(left, y, width, height)); y += height; } } d->mAnimate = false; } /************************************************ ************************************************/ QRect GridLayout::occupiedGeometry() const { return d_func()->mOccupiedGeometry; } ukui-panel-3.0.6.4/panel/common/ukuiplugininfo.cpp0000644000175000017500000001166114203402514020517 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2011 Razor team * Authors: * Alexander Sokoloff * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "ukuiplugininfo.h" #include #include #include #include #include #include #include using namespace UKUi; /************************************************ ************************************************/ PluginInfo::PluginInfo(): XdgDesktopFile() { } /************************************************ ************************************************/ bool PluginInfo::load(const QString& fileName) { XdgDesktopFile::load(fileName); mId = QFileInfo(fileName).completeBaseName(); return isValid(); } /************************************************ ************************************************/ bool PluginInfo::isValid() const { return XdgDesktopFile::isValid(); } /************************************************ ************************************************/ QLibrary* PluginInfo::loadLibrary(const QString& libDir) const { const QFileInfo fi = QFileInfo(fileName()); const QString path = fi.canonicalPath(); const QString baseName = value(QL1S("X-UKUi-Library"), fi.completeBaseName()).toString(); const QString soPath = QDir(libDir).filePath(QString::fromLatin1("lib%2.so").arg(baseName)); QLibrary* library = new QLibrary(soPath); if (!library->load()) { qWarning() << QString::fromLatin1("Can't load plugin lib \"%1\"").arg(soPath) << library->errorString(); delete library; return 0; } const QString locale = QLocale::system().name(); QTranslator* translator = new QTranslator(library); translator->load(QString::fromLatin1("%1/%2/%2_%3.qm").arg(path, baseName, locale)); qApp->installTranslator(translator); return library; } /************************************************ ************************************************/ PluginInfoList PluginInfo::search(const QStringList& desktopFilesDirs, const QString& serviceType, const QString& nameFilter) { QList res; QSet processed; for (const QString &desktopFilesDir : desktopFilesDirs) { const QDir dir(desktopFilesDir); const QFileInfoList files = dir.entryInfoList(QStringList(nameFilter), QDir::Files | QDir::Readable); for (const QFileInfo &file : files) { if (processed.contains(file.fileName())) continue; processed << file.fileName(); PluginInfo item; item.load(file.canonicalFilePath()); if (item.isValid() && item.serviceType() == serviceType) res.append(item); } } return res; } /************************************************ ************************************************/ PluginInfoList PluginInfo::search(const QString& desktopFilesDir, const QString& serviceType, const QString& nameFilter) { return search(QStringList(desktopFilesDir), serviceType, nameFilter); } /************************************************ ************************************************/ QDebug operator<<(QDebug dbg, const UKUi::PluginInfo &pluginInfo) { dbg.nospace() << QString::fromLatin1("%1").arg(pluginInfo.id()); return dbg.space(); } /************************************************ ************************************************/ QDebug operator<<(QDebug dbg, const UKUi::PluginInfo * const pluginInfo) { return operator<<(dbg, *pluginInfo); } /************************************************ ************************************************/ QDebug operator<<(QDebug dbg, const PluginInfoList& list) { dbg.nospace() << QL1C('('); for (int i=0; i Luís Pereira * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "ukuitranslator.h" #include #include #include #include #include #include #include #include #include using namespace UKUi; bool translate(const QString &name, const QString &owner = QString()); /************************************************ ************************************************/ QStringList *getSearchPaths() { static QStringList *searchPath = 0; if (searchPath == 0) { searchPath = new QStringList(); *searchPath << XdgDirs::dataDirs(QL1C('/') + QL1S(UKUI_RELATIVE_SHARE_TRANSLATIONS_DIR)); *searchPath << QL1S(UKUI_SHARE_TRANSLATIONS_DIR); searchPath->removeDuplicates(); } return searchPath; } /************************************************ ************************************************/ QStringList UKUi::Translator::translationSearchPaths() { return *(getSearchPaths()); } /************************************************ ************************************************/ void Translator::setTranslationSearchPaths(const QStringList &paths) { QStringList *p = getSearchPaths(); p->clear(); *p << paths; } /************************************************ ************************************************/ #if (QT_VERSION < QT_VERSION_CHECK(5,7,0)) bool translate(const QString &name, const QString &owner) { const QString locale = QLocale::system().name(); QTranslator *appTranslator = new QTranslator(qApp); QStringList *paths = getSearchPaths(); // for(const QString &path : qAsConst(*paths)) for(int i=0 ;i<(*paths).size();i++) { QStringList subPaths; if (!owner.isEmpty()) { subPaths << (*paths)[i] + QL1C('/') + owner + QL1C('/') + name; } else { subPaths << (*paths)[i] + QL1C('/') + name; subPaths << (*paths)[i]; } // for(const QString &p : qAsConst(subPaths)) for(int i=0;iload(name + QL1C('_') + locale, p)) { QCoreApplication::installTranslator(appTranslator); return true; } else if (locale == QLatin1String("C") || locale.startsWith(QLatin1String("en"))) { // English is the default. Even if there isn't an translation // file, we return true. It's translated anyway. delete appTranslator; return true; } } } // If we got here, no translation was loaded. appTranslator has no use. delete appTranslator; return false; } #endif #if (QT_VERSION >= QT_VERSION_CHECK(5,7,0)) bool translate(const QString &name, const QString &owner) { const QString locale = QLocale::system().name(); QTranslator *appTranslator = new QTranslator(qApp); QStringList *paths = getSearchPaths(); for(const QString &path : qAsConst(*paths)) { QStringList subPaths; if (!owner.isEmpty()) { subPaths << path + QL1C('/') + owner + QL1C('/') + name; } else { subPaths << path + QL1C('/') + name; subPaths << path; } for(const QString &p : qAsConst(subPaths)) { if (appTranslator->load(name + QL1C('_') + locale, p)) { QCoreApplication::installTranslator(appTranslator); return true; } else if (locale == QLatin1String("C") || locale.startsWith(QLatin1String("en"))) { // English is the default. Even if there isn't an translation // file, we return true. It's translated anyway. delete appTranslator; return true; } } } // If we got here, no translation was loaded. appTranslator has no use. delete appTranslator; return false; } #endif /************************************************ ************************************************/ bool Translator::translateApplication(const QString &applicationName) { const QString locale = QLocale::system().name(); QTranslator *qtTranslator = new QTranslator(qApp); if (qtTranslator->load(QL1S("qt_") + locale, QLibraryInfo::location(QLibraryInfo::TranslationsPath))) { qApp->installTranslator(qtTranslator); } else { delete qtTranslator; } if (!applicationName.isEmpty()) return translate(applicationName); else return translate(QFileInfo(QCoreApplication::applicationFilePath()).baseName()); } /************************************************ ************************************************/ bool Translator::translateLibrary(const QString &libraryName) { static QSet loadedLibs; if (loadedLibs.contains(libraryName)) return true; loadedLibs.insert(libraryName); return translate(libraryName); } bool Translator::translatePlugin(const QString &pluginName, const QString& type) { static QSet loadedPlugins; const QString fullName = type % QL1C('/') % pluginName; if (loadedPlugins.contains(fullName)) return true; loadedPlugins.insert(pluginName); return translate(pluginName, type); } static void loadSelfTranslation() { Translator::translateLibrary(QLatin1String("libukui")); } Q_COREAPP_STARTUP_FUNCTION(loadSelfTranslation) ukui-panel-3.0.6.4/panel/common/ukuiapplication.cpp0000644000175000017500000001377314203402514020656 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2012-2013 Razor team * Authors: * Petr Vanek * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include #include "ukuiapplication.h" #include "ukuisettings.h" #include using namespace UKUi; #define COLOR_DEBUG "\033[32;2m" #define COLOR_WARN "\033[33;2m" #define COLOR_CRITICAL "\033[31;1m" #define COLOR_FATAL "\033[33;1m" #define COLOR_RESET "\033[0m" #define QAPP_NAME qApp ? qApp->objectName().toUtf8().constData() : "" #include #include #include #include #include #include #include #include #include /*! \brief Log qDebug input to file Used only in pure Debug builds or when is the system environment variable UKUI_DEBUG set */ void dbgMessageOutput(QtMsgType type, const QMessageLogContext &ctx, const QString & msgStr) { Q_UNUSED(ctx) QByteArray msgBuf = msgStr.toUtf8(); const char* msg = msgBuf.constData(); QDir dir(XdgDirs::configHome() + QLatin1String("/ukui")); dir.mkpath(QL1S(".")); const char* typestr; const char* color; switch (type) { case QtDebugMsg: typestr = "Debug"; color = COLOR_DEBUG; break; case QtWarningMsg: typestr = "Warning"; color = COLOR_WARN; break; case QtFatalMsg: typestr = "Fatal"; color = COLOR_FATAL; break; default: // QtCriticalMsg typestr = "Critical"; color = COLOR_CRITICAL; } QByteArray dt = QDateTime::currentDateTime().toString(QL1S("yyyy-MM-dd hh:mm:ss.zzz")).toUtf8(); if (isatty(STDERR_FILENO)) fprintf(stderr, "%s %s(%p) %s: %s%s\n", color, QAPP_NAME, static_cast(qApp), typestr, msg, COLOR_RESET); else fprintf(stderr, "%s(%p) %s: %s\n", QAPP_NAME, static_cast(qApp), typestr, msg); FILE *f = fopen(dir.absoluteFilePath(QL1S("debug.log")).toUtf8().constData(), "a+"); fprintf(f, "%s %s(%p) %s: %s\n", dt.constData(), QAPP_NAME, static_cast(qApp), typestr, msg); fclose(f); if (type == QtFatalMsg) abort(); } Application::Application(int &argc, char** argv) : QApplication(argc, argv) { setWindowIcon(QIcon(QFile::decodeName(UKUI_GRAPHICS_DIR) + QL1S("/ukui_logo.png"))); connect(Settings::globalSettings(), &GlobalSettings::ukuiThemeChanged, this, &Application::updateTheme); updateTheme(); } Application::Application(int &argc, char** argv, bool handleQuitSignals) : Application(argc, argv) { if (handleQuitSignals) { QList signo_list = {SIGINT, SIGTERM, SIGHUP}; connect(this, &Application::unixSignal, [this, signo_list] (int signo) { if (signo_list.contains(signo)) quit(); }); listenToUnixSignals(signo_list); } } void Application::updateTheme() { const QString styleSheetKey = QFileInfo(applicationFilePath()).fileName(); setStyleSheet(ukuiTheme.qss(styleSheetKey)); emit themeChanged(); } namespace { class SignalHandler { public: static void signalHandler(int signo) { const int ret = write(instance->mSignalSock[0], &signo, sizeof (int)); if (sizeof (int) != ret) qCritical("unable to write into socketpair: %s", strerror(errno)); } public: template SignalHandler(Application * app, Lambda signalEmitter) : mSignalSock{-1, -1} { if (0 != socketpair(AF_UNIX, SOCK_STREAM, 0, mSignalSock)) { qCritical("unable to create socketpair for correct signal handling: %s", strerror(errno)); return; } mNotifier.reset(new QSocketNotifier(mSignalSock[1], QSocketNotifier::Read)); QObject::connect(mNotifier.data(), &QSocketNotifier::activated, app, [this, signalEmitter] { int signo = 0; int ret = read(mSignalSock[1], &signo, sizeof (int)); if (sizeof (int) != ret) qCritical("unable to read signal from socketpair, %s", strerror(errno)); signalEmitter(signo); }); } ~SignalHandler() { close(mSignalSock[0]); close(mSignalSock[1]); } void listenToSignals(QList const & signoList) { struct sigaction sa; sa.sa_handler = signalHandler; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; for (auto const & signo : signoList) sigaction(signo, &sa, nullptr); } public: static QScopedPointer instance; private: int mSignalSock[2]; QScopedPointer mNotifier; }; QScopedPointer SignalHandler::instance; } void Application::listenToUnixSignals(QList const & signoList) { static QScopedPointer signal_notifier; if (SignalHandler::instance.isNull()) SignalHandler::instance.reset(new SignalHandler{this, [this] (int signo) { emit unixSignal(signo); }}); SignalHandler::instance->listenToSignals(signoList); } ukui-panel-3.0.6.4/panel/common/ukuisingleapplication.cpp0000644000175000017500000000711114203402514022045 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2014 LXQt team * Authors: * Luís Pereira * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "ukuisingleapplication.h" #include "singleapplicationadaptor.h" #include #include #include #include #include #include using namespace UKUi; SingleApplication::SingleApplication(int &argc, char **argv, StartOptions options) : Application(argc, argv), mActivationWindow(0) { QString service = QString::fromLatin1("org.ukui.%1").arg(QApplication::applicationName()); QDBusConnection bus = QDBusConnection::sessionBus(); if (!bus.isConnected()) { QLatin1String errorMessage("Can't connect to the D-Bus session bus\n" "Make sure the D-Bus daemon is running"); /* ExitOnDBusFailure is the default. Any value other than NoExitOnDBusFailure will be taken as ExitOnDBusFailure (the default). */ if (options == NoExitOnDBusFailure) { qDebug() << Q_FUNC_INFO << errorMessage; return; } else { qCritical() << Q_FUNC_INFO << errorMessage; QTimer::singleShot(0, [this] { exit(1); }); } } bool registered = (bus.registerService(service) == QDBusConnectionInterface::ServiceRegistered); if (registered) { // We are the primary instance SingleApplicationAdaptor *mAdaptor = new SingleApplicationAdaptor(this); QLatin1String objectPath("/"); bus.registerObject(objectPath, mAdaptor, QDBusConnection::ExportAllSlots); } else { // We are the second outstance QDBusMessage msg = QDBusMessage::createMethodCall(service, QStringLiteral("/"), QStringLiteral("org.ukui.SingleApplication"), QStringLiteral("activateWindow")); QDBusConnection::sessionBus().send(msg); QTimer::singleShot(0, [this] { exit(0); }); } } SingleApplication::~SingleApplication() { } void SingleApplication::setActivationWindow(QWidget *w) { mActivationWindow = w; } QWidget *SingleApplication::activationWindow() const { return mActivationWindow; } void SingleApplication::activateWindow() { if (mActivationWindow) { mActivationWindow->show(); WId window = mActivationWindow->effectiveWinId(); KWindowInfo info(window, NET::WMDesktop); int windowDesktop = info.desktop(); if (windowDesktop != KWindowSystem::currentDesktop()) KWindowSystem::setCurrentDesktop(windowDesktop); KWindowSystem::activateWindow(window); } else { qDebug() << Q_FUNC_INFO << "activationWindow not set or null"; } } ukui-panel-3.0.6.4/panel/common/dbus/0000755000175000017500000000000014203402514015673 5ustar fengfengukui-panel-3.0.6.4/panel/common/dbus/org.ukui.SingleApplication.xml0000644000175000017500000000041614203402514023565 0ustar fengfeng ukui-panel-3.0.6.4/panel/common/ukuisingleapplication.h0000644000175000017500000001117514203402514021517 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2014 LXQt team * Authors: * Luís Pereira * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef UKUISINGLEAPPLICATION_H #define UKUISINGLEAPPLICATION_H #include "ukuiapplication.h" class QWidget; namespace UKUi { /*! \class SingleApplication * \brief The SingleApplication class provides an single instance Application. * * This class allows the user to create applications where only one instance * is allowed to be running at an given time. If the user tries to launch * another instance, the already running instance will be activated instead. * * The user has to set the activation window with setActivationWindow. If it * doesn't the second instance will quietly exit without activating the first * instance window. In any case only one instance is allowed. * * These classes depend on D-Bus and KF5::WindowSystem * * \code * * // Original code * int main(int argc, char **argv) * { * UKUi::Application app(argc, argv); * * MainWidget w; * w.show(); * * return app.exec(); * } * * // Using the library * int main(int argc, char **argv) * { * UKUi::SingleApplication app(argc, argv); * * MainWidget w; * app.setActivationWindow(&w); * w.show(); * * return app.exec(); * } * \endcode * \sa SingleApplication */ class UKUI_API SingleApplication : public Application { Q_OBJECT public: /*! * \brief Options to control the D-Bus failure related application behaviour * * By default (ExitOnDBusFailure) if an instance can't connect to the D-Bus * session bus, that instance calls ::exit(1). Not even the first instance * will run. Connecting to the D-Bus session bus is an condition to * guarantee that only one instance will run. * * If an user wants to allow an application to run without D-Bus, it must * use the NoExitOnDBusFailure option. * * ExitOnDBusFailure is the default. */ enum StartOptions { /** Exit if the connection to the D-Bus session bus fails. * It's the default */ ExitOnDBusFailure, /** Don't exit if the connection to the D-Bus session bus fails.*/ NoExitOnDBusFailure }; Q_ENUM(StartOptions) /*! * \brief Construct a UKUi SingleApplication object. * \param argc standard argc as in QApplication * \param argv standard argv as in QApplication * \param options Control the on D-Bus failure application behaviour * * \sa StartOptions. */ SingleApplication(int &argc, char **argv, StartOptions options = ExitOnDBusFailure); virtual ~SingleApplication(); /*! * \brief Sets the activation window. * \param w activation window. * * Sets the activation window of this application to w. The activation * window is the widget that will be activated by \a activateWindow(). * * \sa activationWindow() \sa activateWindow(); */ void setActivationWindow(QWidget *w); /*! * \brief Gets the current activation window. * \return The current activation window. * * \sa setActivationWindow(); */ QWidget *activationWindow() const; public Q_SLOTS: /*! * \brief Activates this application activation window. * * Changes to the desktop where this applications is. It then de-minimizes, * raises and activates the application's activation window. * If no activation window has been set, this function does nothing. * * \sa setActivationWindow(); */ void activateWindow(); private: QWidget *mActivationWindow; }; #if defined(ukuiSingleApp) #undef ukuiSingleApp #endif #define ukuiSingleApp (static_cast(qApp)) } // namespace UKUi #endif // UKUISINGLEAPPLICATION_H ukui-panel-3.0.6.4/panel/common/ukuiplugininfo.h0000644000175000017500000000763614203402514020173 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2011 Razor team * Authors: * Alexander Sokoloff * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef UKUIPLUGININFO_H #define UKUIPLUGININFO_H #include #include #include #include #include #include "ukuiglobals.h" #include class QLibrary; namespace UKUi { /*! Every plugin needs a .desktop file that describes it. The basename of this file must be same as the basename of the plugin library. ukuipanel_clock2.desktop file [Desktop Entry] Type=Service ServiceTypes=UKUiPanel/Plugin Name=Clock Comment=Clock and calendar PluginInfo class gives the interface for reading the values from the plugin .desktop file. This is a pure virtual class, you must implement libraryDir(), translationDir(), and instance() methods. */ class UKUI_API PluginInfo: public XdgDesktopFile { public: /// Constructs a PluginInfo object for accessing the info stored in the .desktop file. explicit PluginInfo(); //! Reimplemented from XdgDesktopFile. virtual bool load(const QString& fileName); //! Reimplemented from XdgDesktopFile. //PluginInfo& operator=(const PluginInfo& other); //! Returns identification string of this plugin, identified plugin type. Now id is part of the filename. QString id() const { return mId; } //! This function is provided for convenience. It's equivalent to calling value("ServiceTypes").toString(). QString serviceType() const { return value(QL1S("ServiceTypes")).toString(); } //! Reimplemented from XdgDesktopFile. virtual bool isValid() const; /*! Loads the library and returns QLibrary object if the library was loaded successfully; otherwise returns 0. @parm libDir directory where placed the plugin .so file. */ QLibrary* loadLibrary(const QString& libDir) const; /*! Returns a list of PluginInfo objects for the matched files in the directories. @param desktopFilesDirs - scanned directories names. @param serviceType - type of the plugin, for example "UKUiPanel/Plugin". @param nameFilter - wildcard filter that understands * and ? wildcards. If the same filename is located under multiple directories only the first file should be used. */ static QList search(const QStringList& desktopFilesDirs, const QString& serviceType, const QString& nameFilter = QLatin1String("*")); /// This function is provided for convenience. It's equivalent to new calling search(QString(desktopFilesDir), serviceType, nameFilter) static QList search(const QString& desktopFilesDir, const QString& serviceType, const QString& nameFilter = QLatin1String("*")); private: QString mId; }; typedef QList PluginInfoList; } // namespace UKUi QDebug operator<<(QDebug dbg, const UKUi::PluginInfo& pi); QDebug operator<<(QDebug dbg, const UKUi::PluginInfo* const pi); QDebug operator<<(QDebug dbg, const UKUi::PluginInfoList& list); QDebug operator<<(QDebug dbg, const UKUi::PluginInfoList* const pluginInfoList); #endif // UKUIPLUGININFO_H ukui-panel-3.0.6.4/panel/common/ukuisettings.h0000644000175000017500000001522714203402514017654 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2011 Razor team * Authors: * Alexander Sokoloff * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef UKUISETTINGS_H #define UKUISETTINGS_H #include #include #include #include "ukuiglobals.h" class QEvent; namespace UKUi { class SettingsPrivate; class GlobalSettings; /*! \brief User settings handling */ class UKUI_API Settings : public QSettings { Q_OBJECT public: /*! \brief Constructs a Settings object for accessing settings of the module called module, and with parent parent. Settings can be accessed using the standard interface provided by QSettings, but it also provides some convenience functions and signals. \param module a base name of the config file. It's a name without the extension. For example: if you want to open settings for panel create it as Settings("panel"). The function will create all parent directories necessary to create the file. \param parent It's no need to delete this class manually if it's set. */ explicit Settings(const QString& module, QObject* parent = 0); //explicit Settings(QObject* parent=0); explicit Settings(const QSettings* parentSettings, const QString& subGroup, QObject* parent=0); explicit Settings(const QSettings& parentSettings, const QString& subGroup, QObject* parent=0); Settings(const QString &fileName, QSettings::Format format, QObject *parent = 0); ~Settings(); static const GlobalSettings *globalSettings(); /*! Returns the localized value for key. In the desktop file keys may be postfixed by [LOCALE]. If the localized value doesn't exist, returns non lokalized value. If non localized value doesn't exist, returns defaultValue. LOCALE must be of the form lang_COUNTRY.ENCODING@MODIFIER, where _COUNTRY, .ENCODING, and @MODIFIER may be omitted. If no default value is specified, a default QVariant is returned. */ QVariant localizedValue(const QString& key, const QVariant& defaultValue = QVariant()) const; /*! Sets the value of setting key to value. If a localized version of the key already exists, the previous value is overwritten. Otherwise, it overwrites the the un-localized version. */ void setLocalizedValue(const QString &key, const QVariant &value); signals: /*! /brief signal for backward compatibility (emitted whenever settingsChangedFromExternal() or settingsChangedByApp() is emitted) */ void settingsChanged(); /*! /brief signal emitted when the settings file is changed by external application */ void settingsChangedFromExternal(); /*! /brief signal emitted when any setting is changed by this object */ void settingsChangedByApp(); protected: bool event(QEvent *event); protected slots: /*! Called when the config file is changed */ virtual void fileChanged(); private slots: void _fileChanged(QString path); private: void addWatchedFile(QString const & path); private: Q_DISABLE_COPY(Settings) SettingsPrivate* const d_ptr; Q_DECLARE_PRIVATE(Settings) }; class UKUiThemeData; /*! \brief QSS theme handling */ class UKUI_API UKUiTheme { public: /// Constructs a null theme. UKUiTheme(); /*! Constructs an theme from the dir with the given path. If path not absolute (i.e. the theme name only) the relevant dir must be found relative to the $XDG_DATA_HOME + $XDG_DATA_DIRS directories. */ UKUiTheme(const QString &path); /// Constructs a copy of other. This is very fast. UKUiTheme(const UKUiTheme &other); UKUiTheme& operator=(const UKUiTheme &other); ~UKUiTheme(); /// Returns the name of the theme. QString name() const; QString path() const; QString previewImage() const; /// Returns true if this theme is valid; otherwise returns false. bool isValid() const; /*! \brief Returns StyleSheet text (not file name, but real text) of the module called module. Paths in url() C/QSS functions are parsed to be real values for the theme, relative to full path */ QString qss(const QString& module) const; /*! \brief A full path to image used as a wallpaper \param screen is an ID of the screen like in Qt. -1 means default (any) screen. Any other value greater than -1 is the exact screen (in dualhead). In themes the index starts from 1 (ix 1 means 1st screen). \retval QString a file name (including path). */ QString desktopBackground(int screen=-1) const; /// Returns the current ukui theme. static const UKUiTheme ¤tTheme(); /// Returns the all themes found in the system. static QList allThemes(); private: static UKUiTheme* mInstance; QSharedDataPointer d; }; /*! A global pointer referring to the unique UKUiTheme object. It is equivalent to the pointer returned by the UKUiTheme::instance() function. Only one theme object can be created. !*/ #define ukuiTheme UKUiTheme::currentTheme() class UKUI_API SettingsCache { public: explicit SettingsCache(QSettings &settings); explicit SettingsCache(QSettings *settings); virtual ~SettingsCache() {} void loadFromSettings(); void loadToSettings(); private: QSettings &mSettings; QHash mCache; }; class GlobalSettingsPrivate; class GlobalSettings: public Settings { Q_OBJECT public: GlobalSettings(); ~GlobalSettings(); signals: /// Signal emitted when the icon theme has changed. void iconThemeChanged(); /// Signal emitted when the ukui theme has changed. void ukuiThemeChanged(); protected slots: void fileChanged(); private: GlobalSettingsPrivate* const d_ptr; Q_DECLARE_PRIVATE(GlobalSettings) }; } // namespace UKUi #endif // UKUISETTINGS_H ukui-panel-3.0.6.4/panel/common/CMakeLists.txt0000644000175000017500000001467414203402514017512 0ustar fengfeng set(UKUIBT_MINIMUM_VERSION "0.6.0") set(KF5_MINIMUM_VERSION "5.36.0") set(QT_MINIMUM_VERSION "5.7.1") set(QTXDG_MINIMUM_VERSION "3.3.1") # Major UKUi Version, belong to all components set(UKUI_MAJOR_VERSION 0) # Minor UKUi Version, belong to all components set(UKUI_MINOR_VERSION 14) # # Patch Version, belong *only* to the component # UKUi is 0.13 - libukui is at patch version 0 # The official UKUi version will follow libukui. # # In a perfect world all components would have the same major- and minor- and # patch-version as libukui - in real life it will be fine if every component # has it's own patch version within a major/minor life cyle. # set(UKUI_PATCH_VERSION 1) set(UKUI_VERSION ${UKUI_MAJOR_VERSION}.${UKUI_MINOR_VERSION}.${UKUI_PATCH_VERSION}) option(UPDATE_TRANSLATIONS "Update source translation translations/*.ts files" OFF) #find_package(ukui-build-tools ${UKUIBT_MINIMUM_VERSION} REQUIRED) #find_package(Qt5 ${QT_MINIMUM_VERSION} CONFIG REQUIRED Widgets DBus X11Extras LinguistTools) #find_package(Qt5Xdg ${QTXDG_MINIMUM_VERSION} REQUIRED) #find_package(KF5WindowSystem ${KF5_MINIMUM_VERSION} REQUIRED) #find_package(PolkitQt5-1 REQUIRED) #find_package(X11 REQUIRED) message(STATUS "Building ${PROJECT_NAME} with Qt ${Qt5Core_VERSION}") include(CMakePackageConfigHelpers) include(GNUInstallDirs) # Standard directories for installation set(UKUI_PKG_CONFIG_DESCRIPTION "Shared library for UKUi applications") set(HEADERS ukuisettings.h ukuiplugininfo.h ukuiapplication.h ukuisingleapplication.h ukuitranslator.h ukuigridlayout.h ukuiglobals.h ) set(PUBLIC_CLASSES Settings PluginInfo Application SingleApplication Translator PageSelectWidget GridLayout Globals ) set(SOURCES ukuiplugininfo.cpp ukuisettings.cpp ukuiapplication.cpp ukuisingleapplication.cpp ukuitranslator.cpp ukuiprogramfinder.cpp ukuigridlayout.cpp ) set(MOCS ukuisettings.h ukuiscreensaver.h ukuiapplication.h ukuigridlayout.h ) set(FORMS configdialog/ukuiconfigdialog.ui ) file(GLOB UKUI_CONFIG_FILES resources/*.conf) QT5_ADD_DBUS_ADAPTOR(DBUS_ADAPTOR_SRCS dbus/org.ukui.SingleApplication.xml ukuisingleapplication.h UKUi::SingleApplication ) set_property(SOURCE ${DBUS_INTERFACE_SRCS} ${DBUS_ADAPTOR_SRCS} PROPERTY SKIP_AUTOGEN ON) list(APPEND SOURCES "${DBUS_INTERFACE_SRCS}" "${DBUS_ADAPTOR_SRCS}") # KF5WindowSystem is missing here. KF5WindowSystem doesn't provide an .pc file. set(UKUI_PKG_CONFIG_REQUIRES "Qt5Xdg >= ${QTXDG_MINIMUM_VERSION}, Qt5Widgets >= ${QT_MINIMUM_VERSION}, Qt5Xml >= ${QT_MINIMUM_VERSION}, Qt5DBus >= ${QT_MINIMUM_VERSION}, Qt5X11Extras >= ${QT_MINIMUM_VERSION}") # Standard directories for installation include(../../cmake/ukui-build-tools/modules/UKUiPreventInSourceBuilds.cmake) include(../../cmake/ukui-build-tools/modules/UKUiCompilerSettings.cmake) include(../../cmake/ukui-build-tools/modules/UKUiCreatePkgConfigFile.cmake) include(../../cmake/ukui-build-tools/modules/UKUiCreatePortableHeaders.cmake) include(../../cmake/ukui-build-tools/modules/UKUiConfigVars.cmake) set(UKUI_INTREE_INCLUDE_DIR "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/include") set(UKUI_INSTALL_INCLUDE_DIR "${CMAKE_INSTALL_FULL_INCLUDEDIR}/${UKUI_LIBRARY_NAME}") set(UKUI_INSTALL_CMAKE_DIR "${CMAKE_INSTALL_FULL_DATAROOTDIR}/cmake") ## Translations #include(../cmake/ukui-build-tools/modules/UKUiTranslateTs.cmake) #ukui_translate_ts(QM_FILES # UPDATE_TRANSLATIONS # ${UPDATE_TRANSLATIONS} # SOURCES # ${SRCS} # ${FORMS} # INSTALL_DIR # "${UKUI_TRANSLATIONS_DIR}/${PROJECT_NAME}" #) message(STATUS "") message(STATUS "libukui version: ${UKUI_VERSION}") message(STATUS "") # Copy public headers foreach(h ${HEADERS}) get_filename_component(bh ${h} NAME) configure_file(${h} "${UKUI_INTREE_INCLUDE_DIR}/UKUi/${bh}" COPYONLY) endforeach() # Create the portable headers ukui_create_portable_headers(INTREE_PORTABLE_HEADERS NAME_PREFIX "ukui" OUTPUT_DIR "${UKUI_INTREE_INCLUDE_DIR}/UKUi" HEADER_NAMES ${PUBLIC_CLASSES} ) #check_portable_headers(H_FILES ${PUB_HDRS} LINKS "${INTREE_PORTABLE_HEADERS}") #************************************************ # Create in-tree build infrastructure #************************************************ set(CFG_UKUI_TARGETS_FILE "${UKUI_INTREE_TARGETS_FILE}") configure_package_config_file( "${CMAKE_CURRENT_SOURCE_DIR}/cmake/ukui-config.cmake.in" "${CMAKE_BINARY_DIR}/${UKUI_LIBRARY_NAME}-config.cmake" INSTALL_DESTINATION "neverland" # required, altough we don't install it ) #************************************************ # Create installable build infrastructure #************************************************ set(CFG_UKUI_TARGETS_FILE "${UKUI_INSTALL_CMAKE_DIR}/${UKUI_LIBRARY_NAME}/${UKUI_LIBRARY_NAME}-targets.cmake") #install(EXPORT # ${UKUI_LIBRARY_NAME}-targets # DESTINATION "${CMAKE_INSTALL_DATADIR}/cmake/${UKUI_LIBRARY_NAME}" # COMPONENT Devel #) if (Qt5Core_VERSION VERSION_LESS "5.9.0") if (NOT DEFINED WITH_XDG_DIRS_FALLBACK) set(WITH_XDG_DIRS_FALLBACK ON) endif () elseif (WITH_XDG_DIRS_FALLBACK) set(WITH_XDG_DIRS_FALLBACK OFF) message(WARNING "Disabling requested WITH_XDG_DIRS_FALLBACK workaround, as proper implementation is in Qt from v5.9.0") endif () if (WITH_XDG_DIRS_FALLBACK) message(STATUS "Building with homemade QSettings XDG fallback workaround") setByDefault(CUSTOM_QT_5_12_VERSION Yes) if (CUSTOM_QT_5_12_VERSION ) #target_compile_definitions(${UKUI_LIBRARY_NAME} #PRIVATE "WITH_XDG_DIRS_FALLBACK" #) endif(CUSTOM_QT_5_12_VERSION) endif () #install(FILES # ${PUB_HDRS} # DESTINATION "${UKUI_INSTALL_INCLUDE_DIR}/UKUi" # COMPONENT Devel #) #install(FILES # ${INTREE_PORTABLE_HEADERS} # DESTINATION "${UKUI_INSTALL_INCLUDE_DIR}/UKUi" # COMPONENT Devel #) #install(FILES ${UKUI_CONFIG_FILES} # DESTINATION "${CMAKE_INSTALL_FULL_DATADIR}/ukui" # COMPONENT Runtime #) #install(FILES ${POLKIT_FILES} DESTINATION "${POLKITQT-1_POLICY_FILES_INSTALL_DIR}") #************************************************ # Create and install pkgconfig file #************************************************ ukui_create_pkgconfig_file( PACKAGE_NAME ${UKUI_LIBRARY_NAME} DESCRIPTIVE_NAME ${UKUI_LIBRARY_NAME} DESCRIPTION ${UKUI_PKG_CONFIG_DESCRIPTION} INCLUDEDIRS ${UKUI_LIBRARY_NAME} REQUIRES ${UKUI_PKG_CONFIG_REQUIRES} VERSION ${UKUI_VERSION} INSTALL ) #************************************************ ukui-panel-3.0.6.4/panel/common/ukuiapplication.h0000644000175000017500000000523714203402514020317 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2012-2013 Razor team * Authors: * Petr Vanek * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef UKUIAPPLICATION_H #define UKUIAPPLICATION_H #include #include #include "ukuiglobals.h" namespace UKUi { /*! \brief UKUi wrapper around QApplication. * It loads various UKUi related stuff by default (window icon, icon theme...) * * \note This wrapper is intended to be used only inside UKUi project. Using it * in external application will automatically require linking to various * UKUi libraries. * */ class UKUI_API Application : public QApplication { Q_OBJECT public: /*! Construct a UKUi application object. * \param argc standard argc as in QApplication * \param argv standard argv as in QApplication */ Application(int &argc, char **argv); /*! Construct a UKUi application object. * \param argc standard argc as in QApplication * \param argv standard argv as in QApplication * \param handleQuitSignals flag if signals SIGINT, SIGTERM, SIGHUP should be handled internaly (\sa quit() application) */ Application(int &argc, char **argv, bool handleQuitSignals); virtual ~Application() {} /*! Install UNIX signal handler for signals defined in \param signalList * Upon receiving of any of this signals the \sa unixSignal signal is emitted */ void listenToUnixSignals(QList const & signolList); private slots: void updateTheme(); signals: void themeChanged(); /*! Signal is emitted upon receival of registered unix signal * \param signo the received unix signal number */ void unixSignal(int signo); }; #if defined(ukuiApp) #undef ukuiApp #endif #define ukuiApp (static_cast(qApp)) } // namespace UKUi #endif // UKUIAPPLICATION_H ukui-panel-3.0.6.4/panel/common/ukuitranslator.h0000644000175000017500000000470414203402514020203 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2013 LXQt team * Authors: * Alexander Sokoloff Luís Pereira * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef UKUITRANSLATOR_H #define UKUITRANSLATOR_H #include #include "ukuiglobals.h" namespace UKUi { /** The Translator class provides internationalization support for application and librarioes. **/ class UKUI_API Translator { public: /** Returns a list of paths that the application will search translations files. **/ static QStringList translationSearchPaths(); /** Sets the list of directories to search translations. All existing paths will be deleted and the path list will consist of the paths given in paths. **/ static void setTranslationSearchPaths(const QStringList &paths); /** Loads translations for application. If applicationName is not specified, then basename of QCoreApplication::applicationFilePath() is used. Returns true if the translation is successfully loaded; otherwise returns false. **/ static bool translateApplication(const QString &applicationName = QString()); /** Loads translations for application. If applicationName is not specified, then basename of QCoreApplication::applicationFilePath() is used. Returns true if the translation is successfully loaded; otherwise returns false. **/ static bool translateLibrary(const QString &libraryName = QString()); static bool translatePlugin(const QString &pluginName, const QString& type); }; } // namespace UKUi #endif // UKUITRANSLATOR_H ukui-panel-3.0.6.4/panel/common/ukuiglobals.h0000644000175000017500000000261114203402514017430 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2013 - LXQt team * Authors: * Hong Jen Yee (PCMan) * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef _UKUI_GLOBALS_H_ #define _UKUI_GLOBALS_H_ #include #ifdef COMPILE_LIBUKUI #define UKUI_API Q_DECL_EXPORT #else #define UKUI_API Q_DECL_IMPORT #endif #ifndef QL1S #define QL1S(x) QLatin1String(x) #endif #ifndef QL1C #define QL1C(x) QLatin1Char(x) #endif #ifndef QSL #define QSL(x) QStringLiteral(x) #endif #ifndef QBAL #define QBAL(x) QByteArrayLiteral(x) #endif #endif // _UKUI_GLOBALS_H_ ukui-panel-3.0.6.4/panel/common/ukuisettings.cpp0000644000175000017500000005112714203402514020206 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2011 Razor team * Authors: * Alexander Sokoloff * Petr Vanek * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "ukuisettings.h" #include #include #include #include #include #include #include #include #include #include #if QT_VERSION < QT_VERSION_CHECK(5, 6, 0) #include #endif using namespace UKUi; class UKUi::SettingsPrivate { public: SettingsPrivate(Settings* parent, bool useXdgFallback): mFileChangeTimer(0), mAppChangeTimer(0), mAddWatchTimer(0), mParent(parent) { // HACK: we need to ensure that the user (~/.config/ukui/.conf) // exists to have functional mWatcher if (!mParent->contains(QL1S("__userfile__"))) { mParent->setValue(QL1S("__userfile__"), true); #if defined(WITH_XDG_DIRS_FALLBACK) if (useXdgFallback) { //Note: Qt doesn't support the xdg spec regarding the XDG_CONFIG_DIRS //https://bugreports.qt.io/browse/QTBUG-34919 //(Partial) workaround: if the the user specific config file doesn't exist //we try to find some system-wide configuration file and copy all settings into //the user specific file const QString org = mParent->organizationName(); const QString file_name = QFileInfo{mParent->fileName()}.fileName(); QStringList dirs = XdgDirs::configDirs(); #if QT_VERSION < QT_VERSION_CHECK(5, 6, 0) std::reverse(dirs.begin(), dirs.end()); for (auto dir_i = dirs.begin(), dir_e = dirs.end(); dir_i != dir_e; ++dir_i) #else // QT_VERSION for (auto dir_i = dirs.rbegin(), dir_e = dirs.rend(); dir_i != dir_e; ++dir_i) #endif { QDir dir{*dir_i}; if (dir.cd(mParent->organizationName()) && dir.exists(file_name)) { QSettings system_settings{dir.absoluteFilePath(file_name), QSettings::IniFormat}; const QStringList keys = system_settings.allKeys(); for (const QString & key : keys) { mParent->setValue(key, system_settings.value(key)); } } } } #endif mParent->sync(); } mWatcher.addPath(mParent->fileName()); QObject::connect(&(mWatcher), &QFileSystemWatcher::fileChanged, mParent, &Settings::_fileChanged); } QString localizedKey(const QString& key) const; QFileSystemWatcher mWatcher; int mFileChangeTimer; int mAppChangeTimer; int mAddWatchTimer; private: Settings* mParent; }; UKUiTheme* UKUiTheme::mInstance = 0; class UKUi::UKUiThemeData: public QSharedData { public: UKUiThemeData(): mValid(false) {} QString loadQss(const QString& qssFile) const; QString findTheme(const QString &themeName); QString mName; QString mPath; QString mPreviewImg; bool mValid; }; class UKUi::GlobalSettingsPrivate { public: GlobalSettingsPrivate(GlobalSettings *parent): mParent(parent), mThemeUpdated(0ull) { } GlobalSettings *mParent; QString mIconTheme; QString mUKUiTheme; qlonglong mThemeUpdated; }; /************************************************ ************************************************/ Settings::Settings(const QString& module, QObject* parent) : QSettings(QL1S("ukui"), module, parent), d_ptr(new SettingsPrivate(this, true)) { this->setIniCodec(QTextCodec::codecForName("UTF-8")); } /************************************************ ************************************************/ Settings::Settings(const QString &fileName, QSettings::Format format, QObject *parent): QSettings(fileName, format, parent), d_ptr(new SettingsPrivate(this, false)) { } /************************************************ ************************************************/ Settings::Settings(const QSettings* parentSettings, const QString& subGroup, QObject* parent): QSettings(parentSettings->organizationName(), parentSettings->applicationName(), parent), d_ptr(new SettingsPrivate(this, false)) { beginGroup(subGroup); } /************************************************ ************************************************/ Settings::Settings(const QSettings& parentSettings, const QString& subGroup, QObject* parent): QSettings(parentSettings.organizationName(), parentSettings.applicationName(), parent), d_ptr(new SettingsPrivate(this, false)) { beginGroup(subGroup); } /************************************************ ************************************************/ Settings::~Settings() { // because in the Settings::Settings(const QString& module, QObject* parent) // constructor there is no beginGroup() called... if (!group().isEmpty()) endGroup(); delete d_ptr; } bool Settings::event(QEvent *event) { if (event->type() == QEvent::UpdateRequest) { // delay the settingsChanged* signal emitting for: // - checking in _fileChanged // - merging emitting the signals if(d_ptr->mAppChangeTimer) killTimer(d_ptr->mAppChangeTimer); d_ptr->mAppChangeTimer = startTimer(100); } else if (event->type() == QEvent::Timer) { const int timer = static_cast(event)->timerId(); killTimer(timer); if (timer == d_ptr->mFileChangeTimer) { d_ptr->mFileChangeTimer = 0; fileChanged(); // invoke the real fileChanged() handler. } else if (timer == d_ptr->mAppChangeTimer) { d_ptr->mAppChangeTimer = 0; // do emit the signals emit settingsChangedByApp(); emit settingsChanged(); } else if (timer == d_ptr->mAddWatchTimer) { d_ptr->mAddWatchTimer = 0; //try to re-add filename for watching addWatchedFile(fileName()); } } return QSettings::event(event); } void Settings::fileChanged() { sync(); emit settingsChangedFromExternal(); emit settingsChanged(); } void Settings::_fileChanged(QString path) { // check if the file isn't changed by our logic // FIXME: this is poor implementation; should we rather compute some hash of values if changed by external? if (0 == d_ptr->mAppChangeTimer) { // delay the change notification for 100 ms to avoid // unnecessary repeated loading of the same config file if // the file is changed for several times rapidly. if(d_ptr->mFileChangeTimer) killTimer(d_ptr->mFileChangeTimer); d_ptr->mFileChangeTimer = startTimer(1000); } addWatchedFile(path); } void Settings::addWatchedFile(QString const & path) { // D*mn! yet another Qt 5.4 regression!!! // See the bug report: https://github.com/ukui/ukui/issues/441 // Since Qt 5.4, QSettings uses QSaveFile to save the config files. // https://github.com/qtproject/qtbase/commit/8d15068911d7c0ba05732e2796aaa7a90e34a6a1#diff-e691c0405f02f3478f4f50a27bdaecde // QSaveFile will save the content to a new temp file, and replace the old file later. // Hence the existing config file is not changed. Instead, it's deleted and then replaced. // This new behaviour unfortunately breaks QFileSystemWatcher. // After file deletion, we can no longer receive any new change notifications. // The most ridiculous thing is, QFileSystemWatcher does not provide a // way for us to know if a file is deleted. WT*? // Luckily, I found a workaround: If the file path no longer exists // in the watcher's files(), this file is deleted. if(!d_ptr->mWatcher.files().contains(path)) // in some situations adding fails because of non-existing file (e.g. editting file in external program) if (!d_ptr->mWatcher.addPath(path) && 0 == d_ptr->mAddWatchTimer) d_ptr->mAddWatchTimer = startTimer(100); } /************************************************ ************************************************/ const GlobalSettings *Settings::globalSettings() { static QMutex mutex; static GlobalSettings *instance = 0; if (!instance) { mutex.lock(); if (!instance) instance = new GlobalSettings(); mutex.unlock(); } return instance; } /************************************************ LC_MESSAGES value Possible keys in order of matching lang_COUNTRY@MODIFIER lang_COUNTRY@MODIFIER, lang_COUNTRY, lang@MODIFIER, lang, default value lang_COUNTRY lang_COUNTRY, lang, default value lang@MODIFIER lang@MODIFIER, lang, default value lang lang, default value ************************************************/ QString SettingsPrivate::localizedKey(const QString& key) const { QString lang = QString::fromLocal8Bit(qgetenv("LC_MESSAGES")); if (lang.isEmpty()) lang = QString::fromLocal8Bit(qgetenv("LC_ALL")); if (lang.isEmpty()) lang = QString::fromLocal8Bit(qgetenv("LANG")); QString modifier = lang.section(QL1C('@'), 1); if (!modifier.isEmpty()) lang.truncate(lang.length() - modifier.length() - 1); QString encoding = lang.section(QL1C('.'), 1); if (!encoding.isEmpty()) lang.truncate(lang.length() - encoding.length() - 1); QString country = lang.section(QL1C('_'), 1); if (!country.isEmpty()) lang.truncate(lang.length() - country.length() - 1); //qDebug() << "LC_MESSAGES: " << getenv("LC_MESSAGES"); //qDebug() << "Lang:" << lang; //qDebug() << "Country:" << country; //qDebug() << "Encoding:" << encoding; //qDebug() << "Modifier:" << modifier; if (!modifier.isEmpty() && !country.isEmpty()) { QString k = QString::fromLatin1("%1[%2_%3@%4]").arg(key, lang, country, modifier); //qDebug() << "\t try " << k << mParent->contains(k); if (mParent->contains(k)) return k; } if (!country.isEmpty()) { QString k = QString::fromLatin1("%1[%2_%3]").arg(key, lang, country); //qDebug() << "\t try " << k << mParent->contains(k); if (mParent->contains(k)) return k; } if (!modifier.isEmpty()) { QString k = QString::fromLatin1("%1[%2@%3]").arg(key, lang, modifier); //qDebug() << "\t try " << k << mParent->contains(k); if (mParent->contains(k)) return k; } QString k = QString::fromLatin1("%1[%2]").arg(key, lang); //qDebug() << "\t try " << k << mParent->contains(k); if (mParent->contains(k)) return k; //qDebug() << "\t try " << key << mParent->contains(key); return key; } /************************************************ ************************************************/ QVariant Settings::localizedValue(const QString& key, const QVariant& defaultValue) const { Q_D(const Settings); return value(d->localizedKey(key), defaultValue); } /************************************************ ************************************************/ void Settings::setLocalizedValue(const QString &key, const QVariant &value) { Q_D(const Settings); setValue(d->localizedKey(key), value); } /************************************************ ************************************************/ UKUiTheme::UKUiTheme(): d(new UKUiThemeData) { } /************************************************ ************************************************/ UKUiTheme::UKUiTheme(const QString &path): d(new UKUiThemeData) { if (path.isEmpty()) return; QFileInfo fi(path); if (fi.isAbsolute()) { d->mPath = path; d->mName = fi.fileName(); d->mValid = fi.isDir(); } else { d->mName = path; d->mPath = d->findTheme(path); d->mValid = !(d->mPath.isEmpty()); } if (QDir(path).exists(QL1S("preview.png"))) d->mPreviewImg = path + QL1S("/preview.png"); } /************************************************ ************************************************/ QString UKUiThemeData::findTheme(const QString &themeName) { if (themeName.isEmpty()) return QString(); QStringList paths; QLatin1String fallback(UKUI_INSTALL_PREFIX); paths << XdgDirs::dataHome(false); paths << XdgDirs::dataDirs(); if (!paths.contains(fallback)) paths << fallback; #if (QT_VERSION < QT_VERSION_CHECK(5,7,0)) for(int i=0;imValid; } /************************************************ ************************************************/ QString UKUiTheme::name() const { return d->mName; } /************************************************ ************************************************/ QString UKUiTheme::path() const { return d->mPath; } /************************************************ ************************************************/ QString UKUiTheme::previewImage() const { return d->mPreviewImg; } /************************************************ ************************************************/ QString UKUiTheme::qss(const QString& module) const { return d->loadQss(QStringLiteral("%1/%2.qss").arg(d->mPath, module)); } /************************************************ ************************************************/ QString UKUiThemeData::loadQss(const QString& qssFile) const { QFile f(qssFile); if (! f.open(QIODevice::ReadOnly | QIODevice::Text)) { return QString(); } QString qss = QString::fromLocal8Bit(f.readAll()); f.close(); if (qss.isEmpty()) return QString(); // handle relative paths QString qssDir = QFileInfo(qssFile).canonicalPath(); qss.replace(QRegExp(QL1S("url.[ \\t\\s]*"), Qt::CaseInsensitive, QRegExp::RegExp2), QL1S("url(") + qssDir + QL1C('/')); return qss; } /************************************************ ************************************************/ QString UKUiTheme::desktopBackground(int screen) const { QString wallpaperCfgFileName = QString::fromLatin1("%1/wallpaper.cfg").arg(d->mPath); if (wallpaperCfgFileName.isEmpty()) return QString(); QSettings s(wallpaperCfgFileName, QSettings::IniFormat); QString themeDir = QFileInfo(wallpaperCfgFileName).absolutePath(); // There is something strange... If I remove next line the wallpapers array is not found... s.childKeys(); s.beginReadArray(QL1S("wallpapers")); s.setArrayIndex(screen - 1); if (s.contains(QL1S("file"))) return QString::fromLatin1("%1/%2").arg(themeDir, s.value(QL1S("file")).toString()); s.setArrayIndex(0); if (s.contains(QL1S("file"))) return QString::fromLatin1("%1/%2").arg(themeDir, s.value(QL1S("file")).toString()); return QString(); } /************************************************ ************************************************/ const UKUiTheme &UKUiTheme::currentTheme() { static UKUiTheme theme; QString name = Settings::globalSettings()->value(QL1S("theme")).toString(); if (theme.name() != name) { theme = UKUiTheme(name); } return theme; } /************************************************ ************************************************/ QList UKUiTheme::allThemes() { QList ret; QSet processed; QStringList paths; paths << XdgDirs::dataHome(false); paths << XdgDirs::dataDirs(); #if (QT_VERSION < QT_VERSION_CHECK(5,7,0)) for(int i=0;i::const_iterator i = mCache.constBegin(); while(i != mCache.constEnd()) { mSettings.setValue(i.key(), i.value()); ++i; } mSettings.sync(); } /************************************************ ************************************************/ GlobalSettings::GlobalSettings(): Settings(QL1S("ukui")), d_ptr(new GlobalSettingsPrivate(this)) { /*ukui-control-center change the theme rather than panel*/ /* if (value(QL1S("icon_theme")).toString().isEmpty()) { qWarning() << QString::fromLatin1("Icon Theme not set. Fallbacking to Oxygen, if installed"); const QString fallback(QLatin1String("oxygen")); const QDir dir(QLatin1String(UKUI_DATA_DIR) + QLatin1String("/icons")); if (dir.exists(fallback)) { setValue(QL1S("icon_theme"), fallback); sync(); } else { qWarning() << QString::fromLatin1("Fallback Icon Theme (Oxygen) not found"); } } fileChanged(); */ } GlobalSettings::~GlobalSettings() { delete d_ptr; } /************************************************ ************************************************/ void GlobalSettings::fileChanged() { /*ukcc change the theme rather than panel*/ /* Q_D(GlobalSettings); sync(); QString it = value(QL1S("icon_theme")).toString(); if (d->mIconTheme != it) { emit iconThemeChanged(); } QString rt = value(QL1S("theme")).toString(); qlonglong themeUpdated = value(QL1S("__theme_updated__")).toLongLong(); if ((d->mUKUiTheme != rt) || (d->mThemeUpdated != themeUpdated)) { d->mUKUiTheme = rt; emit ukuiThemeChanged(); } emit settingsChangedFromExternal(); emit settingsChanged(); */ } ukui-panel-3.0.6.4/panel/common/cmake/0000755000175000017500000000000014203402514016016 5ustar fengfengukui-panel-3.0.6.4/panel/common/cmake/ukui-config.cmake.in0000644000175000017500000000244114203402514021646 0ustar fengfeng# - Finds the ukui package @PACKAGE_INIT@ if (CMAKE_VERSION VERSION_LESS 3.0.2) message(FATAL_ERROR \"@PROJECT_NAME@ requires at least CMake version 3.0.2\") endif() include(CMakeFindDependencyMacro) find_dependency(Qt5Widgets @QT_MINIMUM_VERSION@) find_dependency(Qt5DBus @QT_MINIMUM_VERSION@) find_dependency(Qt5X11Extras @QT_MINIMUM_VERSION@) find_dependency(Qt5LinguistTools @QT_MINIMUM_VERSION@) find_dependency(Qt5Xdg @QTXDG_MINIMUM_VERSION@) find_dependency(KF5WindowSystem) #find_dependency(ukui-build-tools @UKUIBT_MINIMUM_VERSION@) #include(UKUiConfigVars) include(/usr/share/cmake/ukui-build-tools/modules/UKUiConfigVars.cmake) # - Set version informations set(UKUI_MAJOR_VERSION "@UKUI_MAJOR_VERSION@") set(UKUI_MINOR_VERSION "@UKUI_MINOR_VERSION@") set(UKUI_PATCH_VERSION "@UKUI_PATCH_VERSION@") set(UKUI_VERSION "@UKUI_VERSION@") add_definitions("-DUKUI_MAJOR_VERSION=\"${UKUI_MAJOR_VERSION}\"") add_definitions("-DUKUI_MINOR_VERSION=\"${UKUI_MINOR_VERSION}\"") add_definitions("-DUKUI_PATCH_VERSION=\"${UKUI_PATCH_VERSION}\"") add_definitions("-DUKUI_VERSION=\"${UKUI_VERSION}\"") if (NOT TARGET @UKUI_LIBRARY_NAME@) if (POLICY CMP0024) cmake_policy(SET CMP0024 NEW) endif() include("${CMAKE_CURRENT_LIST_DIR}/ukui-targets.cmake") endif() ukui-panel-3.0.6.4/panel/ukuicontrolstyle.cpp0000644000175000017500000000475114203402514017620 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include UKUiMenu::UKUiMenu(){ } UKUiMenu::~UKUiMenu(){ } void UKUiMenu::paintEvent(QPaintEvent *) { QStyleOption opt; opt.init(this); QPainter p(this); p.setBrush(QBrush(Qt::red)); p.setPen(Qt::black); p.drawRoundedRect(opt.rect,6,6); // p.drawText(rect(), opt. Qt::AlignCenter,); style()->drawPrimitive(QStyle::PE_PanelMenu, &opt, &p, this); } UkuiToolButton::UkuiToolButton(){} UkuiToolButton::~UkuiToolButton(){} void UkuiToolButton::paintTooltipStyle() { //设置QToolTip颜色 QPalette palette = QToolTip::palette(); palette.setColor(QPalette::Inactive,QPalette::ToolTipBase,Qt::black); //设置ToolTip背景色 palette.setColor(QPalette::Inactive,QPalette::ToolTipText, Qt::white); //设置ToolTip字体色 QToolTip::setPalette(palette); // QFont font("Segoe UI", -1, 50); // font.setPixelSize(12); // QToolTip::setFont(font); //设置ToolTip字体 } UKUiFrame::UKUiFrame(){ } UKUiFrame::~UKUiFrame(){ } void UKUiFrame::paintEvent(QPaintEvent *) { QStyleOption opt; opt.init(this); QPainter p(this); p.setBrush(QBrush(QColor(0x13,0x14,0x14,0xb2))); p.setPen(Qt::NoPen); p.setRenderHint(QPainter::Antialiasing); p.drawRoundedRect(opt.rect,6,6); style()->drawPrimitive(QStyle::PE_Frame, &opt, &p, this); } UKUiWidget::UKUiWidget(){ } UKUiWidget::~UKUiWidget(){ } void UKUiWidget::paintEvent(QPaintEvent *) { QStyleOption opt; opt.init(this); QPainter p(this); p.setBrush(QBrush(QColor(0x13,0x14,0x14,0xb2))); p.setPen(Qt::NoPen); p.setRenderHint(QPainter::Antialiasing); p.drawRoundedRect(opt.rect,6,6); style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); } ukui-panel-3.0.6.4/panel/ukuipanellayout.h0000644000175000017500000000557014203402514017061 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2011 Razor team * Authors: * Alexander Sokoloff * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef UKUIPanelLAYOUT_H #define UKUIPanelLAYOUT_H #include #include #include #include #include "iukuipanel.h" #include "ukuipanelglobals.h" class MoveInfo; class QMouseEvent; class QEvent; class Plugin; class LayoutItemGrid; class UKUI_PANEL_API UKUIPanelLayout : public QLayout { Q_OBJECT public: explicit UKUIPanelLayout(QWidget *parent); ~UKUIPanelLayout(); void addItem(QLayoutItem *item); QLayoutItem *itemAt(int index) const; QLayoutItem *takeAt(int index); int count() const; void moveItem(int from, int to, bool withAnimation=false); QSize sizeHint() const; //QSize minimumSize() const; void setGeometry(const QRect &geometry); bool isHorizontal() const; void invalidate(); int lineCount() const; void setLineCount(int value); int lineSize() const; void setLineSize(int value); IUKUIPanel::Position position() const { return mPosition; } void setPosition(IUKUIPanel::Position value); /*! \brief Force the layout to re-read items/plugins "static" configuration */ void rebuild(); static bool itemIsSeparate(QLayoutItem *item); signals: void pluginMoved(Plugin * plugin); public slots: void startMovePlugin(); void finishMovePlugin(); void moveUpPlugin(Plugin * plugin); void addPlugin(Plugin * plugin); private: mutable QSize mMinPluginSize; LayoutItemGrid *mLeftGrid; LayoutItemGrid *mRightGrid; IUKUIPanel::Position mPosition; bool mAnimate; void setGeometryHoriz(const QRect &geometry); void setGeometryVert(const QRect &geometry); void globalIndexToLocal(int index, LayoutItemGrid **grid, int *gridIndex); void globalIndexToLocal(int index, LayoutItemGrid **grid, int *gridIndex) const; void setItemGeometry(QLayoutItem *item, const QRect &geometry, bool withAnimation); }; #endif // UKUIPanelLAYOUT_H ukui-panel-3.0.6.4/panel/iukuipanel.h0000644000175000017500000001101714203402514015765 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2012 Razor team * Authors: * Alexander Sokoloff * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef IUKUIPanel_H #define IUKUIPanel_H #include #include "ukuipanelglobals.h" class IUKUIPanelPlugin; class QWidget; /** **/ class UKUI_PANEL_API IUKUIPanel { public: /** * @brief Specifies the position of the panel on screen. */ enum Position{ PositionBottom, //!< The bottom side of the screen. PositionTop, //!< The top side of the screen. PositionLeft, //!< The left side of the screen. PositionRight //!< The right side of the screen. }; /** * @brief Returns the position of the panel. Possible values for the * return value are described by the Position enum. */ virtual Position position() const = 0; /** * @brief Returns the edge length of the icons that are shown on the panel * in pixels. The icons are square. */ virtual int iconSize() const = 0; virtual int panelSize() const = 0; /** * @brief Returns the number of lines/rows of this panel. */ virtual int lineCount() const = 0; /** * @brief Helper function for convenient direction/alignment checking. * @return True if the panel is on the top or the bottom of the * screen; otherwise returns false. */ bool isHorizontal() const { return position() == PositionBottom || position() == PositionTop; } /** * @brief Helper method that returns the global screen coordinates of the * panel, so you do not need to use QWidget::mapToGlobal() by yourself. * @return The QRect where the panel is located in global screen * coordinates. */ virtual QRect globalGeometry() const = 0; /** * @brief Helper method for calculating the global screen position of a * popup window with size windowSize. * @param absolutePos Contains the global screen coordinates where the * popup should be appear, i.e. the point where the user has clicked. * @param windowSize The size that the window will occupy. * @return The global screen position where the popup window can be shown. */ virtual QRect calculatePopupWindowPos(const QPoint &absolutePos, const QSize &windowSize) const = 0; /** * @brief Helper method for calculating the global screen position of a * popup window with size windowSize. The parameter plugin should be a * plugin * @param plugin Plugin that the popup window will belong to. The position * will be calculated according to the position of the plugin in the panel. * @param windowSize The size that the window will occupy. * @return The global screen position where the popup window can be shown. */ virtual QRect calculatePopupWindowPos(const IUKUIPanelPlugin *plugin, const QSize &windowSize) const = 0; /*! * \brief By calling this function, a plugin (or any other object) notifies the panel * about showing a (standalone) window/menu -> the panel needs this to avoid "hiding" in case any * standalone window is shown. The widget/window must be shown later than this notification call because * the panel needs to observe its show/hide/close events. * * \param w the window that will be shown * */ virtual void willShowWindow(QWidget * w) = 0; /*! * \brief By calling this function, a plugin notifies the panel about change of it's "static" * configuration * * \param plugin the changed plugin * * \sa IUKUIPanelPlugin::isSeparate(), IUKUIPanelPlugin::isExpandable */ virtual void pluginFlagsChanged(const IUKUIPanelPlugin * plugin) = 0; }; #endif // IUKUIPanel_H ukui-panel-3.0.6.4/panel/img/0000755000175000017500000000000014203402514014222 5ustar fengfengukui-panel-3.0.6.4/panel/img/tray-down.svg0000644000175000017500000000062714203402514016674 0ustar fengfeng箭头-向下ukui-panel-3.0.6.4/panel/img/tray-left.svg0000644000175000017500000000061114203402514016650 0ustar fengfeng箭头-向左ukui-panel-3.0.6.4/panel/img/startmenu.svg0000644000175000017500000001316114203402514016767 0ustar fengfeng ukui-panel-3.0.6.4/panel/img/nightmode-light.svg0000644000175000017500000000353214203402514020031 0ustar fengfeng ukui-panel-3.0.6.4/panel/img/nightmode-night.svg0000644000175000017500000000361014203402514020030 0ustar fengfeng ukui-panel-3.0.6.4/panel/img/up.svg0000644000175000017500000000103514203402514015366 0ustar fengfeng ukui-panel-3.0.6.4/panel/img/tick.svg0000644000175000017500000000102614203402514015674 0ustar fengfeng ukui-panel-3.0.6.4/panel/img/taskview.svg0000644000175000017500000000057014203402514016602 0ustar fengfeng32ukui-panel-3.0.6.4/panel/img/tray-right.svg0000644000175000017500000000057514203402514017044 0ustar fengfeng箭头-向右ukui-panel-3.0.6.4/panel/img/setting.svg0000644000175000017500000000177214203402514016427 0ustar fengfeng ukui-panel-3.0.6.4/panel/img/tray-up.svg0000644000175000017500000000062214203402514016344 0ustar fengfeng箭头-向上ukui-panel-3.0.6.4/panel/resources/0000755000175000017500000000000014204636776015504 5ustar fengfengukui-panel-3.0.6.4/panel/resources/ukui-session-tool-action.ini0000644000175000017500000000243714203402514023053 0ustar fengfeng[LockScreen] name=LockScreen name[zh_CN]=锁屏 icon=system-lock-screen-symbolic show=true showInSession=true showInMenu=false showInPanel=true Group=User Action [SwitchUser] name=SwitchUser name[zh_CN]=切换用户 icon=stock-people-symbolic show=true showInSession=true showInMenu=false showInPanel=true Group=User Action [Logout] name=Logout name[zh_CN]=注销 icon=system-logout-symbolic show=true showInSession=true showInMenu=true showInPanel=true Group=User Action [HibernateMode] name=Hibernate Mode name[zh_CN]=休眠 icon=kylin-sleep-symbolic show=true showInSession=true showInMenu=false showInPanel=true Group=User Action Group=Sleep or Hibernate [Sleep Mode] name=Sleep Mode name[zh_CN]=睡眠 icon=system-sleep show=true showInSession=true showInMenu=true showInPanel=true Group=Sleep or Hibernate [Restart] name=Restart name[zh_CN]=重启 icon=system-restart-symbolic show=true showInSession=true showInMenu=true showInPanel=true Group=Sleep or Hibernate [TimeShutdown] name=TimeShutdown name[zh_CN]=定时开关机 icon=system-restart-symbolic show=true showInSession=false showInMenu=false showInPanel=true Group=Power Supply [PowerOff] name=Power Off name[zh_CN]=关机 icon=system-shutdown-symbolic show=true showInSession=true showInMenu=false showInPanel=true Group=Power Supply ukui-panel-3.0.6.4/panel/resources/ukui-panel_zh_CN.qm0000644000175000017500000001231614203402514021155 0ustar fengfeng R ``v"aRNOܐ { @5LEɾUʨ]ʴ5 ʶ-U@57  l 8| b$ bUm )b ) )? zN5 9N ӱ $2 &? ( V\ u "  G u Pt ` 94 " HL t58w} ~*}WD WD 0gޕ>~ i nNRh Config panelCalendarActiveLabel eNeg Time and DateCalendarActiveLabel eegnTime and Date SettingCalendarActiveLabelQIvN:zzblank CD FDClickWidget}N:zzthe capacity is empty FDClickWidget MainWindow MainWindowusb management tool MainWindow nYj!_Set Up NightModeNightModeButtonYj!_Turn On NightModeNightModeButton Yj!_Qsnight mode closeNightModeButton Yj!__T/night mode openNightModeButton Yj!_Qsnightmode closedNightModeButton Yj!__T/nightmode openedNightModeButtonQIvN:zzblank CD QClickWidget}N:zzthe capacity is empty QClickWidget弹出 QClickWidgetf>y:hLb Show Desktop ShowDesktop Space type:SpacerConfiguration Space width:SpacerConfigurationSpacer SettingsSpacerConfigurationdottedSpacerConfiguration expandableSpacerConfigurationfixedSpacerConfiguration invisibleSpacerConfigurationlinedSpacerConfigurationOw Hibernate ModeStartMenuButton\O Lock ScreenStartMenuButtonlLogoutStartMenuButtonQsg: Power OffStartMenuButtonu5n Power SupplyStartMenuButtonT/RestartStartMenuButtonwaw  Sleep ModeStartMenuButton Ow bwaw Sleep or HibernateStartMenuButtonRcbu(b7 Switch UserStartMenuButton[eQsg: TimeShutdownStartMenuButton_Y˃SU UKUI MenuStartMenuButtonu(b7dO\ User ActionStartMenuButtonQsN About Kylin UKUIPaneletOMnAdjustment Position UKUIPaneletY'\Adjustment Size UKUIPanelN Bottom UKUIPanel NRh Hide Panel UKUIPanelY'\:[Large UKUIPanel]Left UKUIPanel [NRhLock This Panel UKUIPanelN-\:[Medium UKUIPanel Remove Panel UKUIPanelERemoving a panel can not be undone. Do you want to remove this panel? UKUIPanelSRight UKUIPanelf>y:hLb Show Desktop UKUIPanelf>y:Yj!_c Show Nightmode UKUIPanel |~vщVhShow System Monitor UKUIPanelf>y:NRVc  Show Taskview UKUIPanel\\:[Small UKUIPanelN Up UKUIPanel_ Drop Error UKUITaskBar"_'%1'elՈmRR0_T/Rh9File/URL '%1' cannot be embedded into QuickLaunch for now UKUITaskBar &All DesktopsUKUITaskButton&Qs&CloseUKUITaskButton&LayerUKUITaskButton&MoveUKUITaskButton&NormalUKUITaskButton&RestoreUKUITaskButton&To Current DesktopUKUITaskButtonAlways on &bottomUKUITaskButtonAlways on &topUKUITaskButton ApplicationUKUITaskButton Desktop &%1UKUITaskButton Ma&ximizeUKUITaskButtonMaximize horizontallyUKUITaskButtonMaximize verticallyUKUITaskButton Mi&nimizeUKUITaskButtonResi&zeUKUITaskButton Roll downUKUITaskButtonRoll upUKUITaskButton To &DesktopUKUITaskButtonNNRhSmV[delete from quicklaunchUKUITaskButton~Group UKUITaskGroupQsclose UKUITaskGroupWidgetUKUITaskWidgetnvaboveUKUITaskWidgetSmnvclearUKUITaskWidgetQscloseUKUITaskWidgetgY'SmaximazeUKUITaskWidgetg\SminimizeUKUITaskWidgetSrestoreUKUITaskWidgetDialogUkuiWebviewDialogConfiguration filemain!Use alternate configuration file.mainukui-panel-3.0.6.4/panel/resources/ukui-panel_bo.ts0000644000175000017500000017447414203402514020603 0ustar fengfeng AddPluginDialog Add Plugins Search: Add Widget Close (only one instance can run at a time) CalendarActiveLabel Time and Date Setting Config panel ConfigDialog Dialog ConfigPanelDialog Configure Panel Panel Widgets ConfigPanelWidget Configure panel Size <p>Negative pixel value sets the panel length to that many pixels less than available screen space.</p><p/><p><i>E.g. "Length" set to -100px, screen size is 1000px, then real panel length will be 900 px.</i></p> Size: Length: % px px Icon size: Rows: Alignment && position Alignment: Left Center Right Position: A&uto-hide Zero means no animation Animation duration: ms Zero means no delay Show with delay: Visible thin margin for hidden panel Don't allow maximized windows go under the panel window Reserve space on display Custom styling Font color: Background color: Background opacity: <small>Compositing is required for panel transparency.</small> Background image: A partial workaround for widget styles that cannot give a separate theme to the panel. You might also want to disable: UKUi Appearance Configuration → Icons Theme → Colorize icons based on widget style (palette) Override icon &theme Icon theme for panels: Top of desktop Left of desktop Right of desktop Bottom of desktop Top of desktop %1 Left of desktop %1 Right of desktop %1 Bottom of desktop %1 Top Bottom Pick color Pick image Images (*.png *.gif *.jpg) ConfigPluginsWidget Configure Plugins Note: changes made in this page cannot be reset. Move up ... Move down Add Remove Configure IndicatorCalendar '<b>'HH:mm:ss'</b><br/><font size="-2">'ddd, d MMM yyyy'<br/>'TT'</font>' MainWindow MainWindow usb management tool NightModeButton please install Newest ukui-control-center first Turn On NightMode Set Up NightMode nightmode open nightmode close don't contains the keys style-name please install ukui-theme first please install gtk-theme first QClickWidget 弹出 QCoreApplication Choose the page to be shown. QObject Power Manager Error QDBusInterface is invalid Power Manager Error (D-BUS call) QuickLaunchButton move to left move to right delete from quicklaunch ShowDesktop Show Desktop SpacerConfiguration Spacer Settings Space width: Space type: fixed expandable lined dotted invisible TaskView Show Taskview UKUIPanel Panel Set up Panel Show Taskview Show Desktop Show System Monitor Small Media Large Adjustment Size Up Bottom Left Right Adjustment Position Lock This Panel Remove Panel Dialog Title Removing a panel can not be undone. Do you want to remove this panel? UKUIQuickLaunch Drop Error File/URL '%1' cannot be embedded into QuickLaunch for now Drop application icons here UKUIStartMenuButton Lock Screen Switch User LogOut Restart Power Off UKUITaskButton Application To &Desktop &All Desktops Desktop &%1 &To Current Desktop &Move Resi&ze Ma&ximize Maximize vertically Maximize horizontally &Restore Mi&nimize Roll down Roll up &Layer Always on &top &Normal Always on &bottom &Close UKUITaskGroup Group close UKUITaskbarConfiguration Task Manager Settings General Show only windows from desktop Show only windows from &panel's screen Show only minimized windows Raise minimized windows on current desktop Close on middle-click Cycle windows on wheel scrolling Window &grouping Show popup on mouse hover Appearance Button style Maximum button width px Maximum button height Auto&rotate buttons when the panel is vertical Use icons by WindowClass, if available Icon and text Only icon Only text Current UKUi::MessageBox UKUi Power Manager Error Hibernate failed. UKUi::NotificationPrivate Notifications Fallback UKUi::PowerManager Hibernate Suspend Reboot Shutdown Logout UKUi Session Suspend Do you want to really suspend your computer?<p>Suspends the computer into a low power state. System state is not preserved if the power is lost. UKUi Session Hibernate Do you want to really hibernate your computer?<p>Hibernates the computer into a low power state. System state is preserved if the power is lost. UKUi Session Reboot Do you want to really restart your computer? All unsaved work will be lost... UKUi Session Shutdown Do you want to really switch off your computer? All unsaved work will be lost... UKUi Session Logout Do you want to really logout? All unsaved work will be lost... UKUi Power Manager Error Hibernate failed. Suspend failed. UKUi::ScreenSaver Screen Saver Error An error occurred starting screensaver. Syntax error in xdg-screensaver arguments. Screen Saver Activation Error An error occurred starting screensaver. Ensure you have xscreensaver installed and running. An error occurred starting screensaver. Action 'activate' failed. Ensure you have xscreensaver installed and running. An error occurred starting screensaver. Unknown error - undocumented return value from xdg-screensaver: %1. Lock Screen UkuiWebviewDialog Dialog ejectInterface usb has been unplugged safely main Use alternate configuration file. Configuration file ukui-panel-3.0.6.4/panel/resources/panel-commission.sh0000644000175000017500000000154414204636776021321 0ustar fengfeng#!/bin/bash ## 定制版本的配置文件初始化处理 #判断文件是否存在 commissionFile="${HOME}/.config/ukui/panel-commission.ini" if [[ ! -f "$commissionFile" ]]; then echo "file not exit" cp /usr/share/ukui/ukui-panel/panel-commission.ini ${HOME}/.config/ukui else echo "file exit" fi ## 华为990 屏蔽休眠接口 env | grep "XDG_SESSION_TYPE=wayland" if [ $? -ne 0 ]; then echo " " else echo "华为990" #sed -i 's/hibernate=show/hibernate=hide/' ${HOME}/.config/ukui/panel-commission.ini fi ## 华为990 屏蔽夜间模式 env | grep "XDG_SESSION_TYPE=wayland" if [ $? -ne 0 ]; then echo " " else echo "华为990" while read line1 do if [[ $line1 == *nightmode* ]];then sed -i 's/nightmode=show/nightmode=hide/' ${HOME}/.config/ukui/panel-commission.ini fi done < ${HOME}/.config/ukui/panel-commission.ini fi ukui-panel-3.0.6.4/panel/resources/panel.conf0000644000175000017500000000320414203402514017425 0ustar fengfengpanels=panel1 [panel1] alignment=-1 animation-duration=100 desktop=0 hidable=false lineCount=1 lockPanel=false plugins=startbar,taskbar,statusnotifier,calendar, nightmode,showdesktop position=Bottom reserve-space=true show-delay=0 visible-margin=true width=100 width-percent=true [startmenu] type=startmenu [quicklaunch] alignment=Left apps\1\desktop=/usr/share/applications/peony.desktop apps\2\desktop=/usr/share/applications/kylin-software-center.desktop apps\3\desktop=/usr/share/applications/qaxbrowser-safe.desktop apps\4\desktop=/usr/share/applications/wps-office-wps.desktop apps\size=4 type=quicklaunch [taskbar] alignment=Left apps\1\desktop=/usr/share/applications/peony.desktop apps\1\exec= apps\1\file= apps\1\name= apps\2\desktop=/usr/share/applications/qaxbrowser-safe.desktop apps\2\exec= apps\2\file= apps\2\name= apps\3\desktop=/usr/share/applications/wps-office-prometheus.desktop apps\3\exec= apps\3\file= apps\3\name= apps\4\desktop=/usr/share/applications/kylin-software-center.desktop apps\4\exec= apps\4\file= apps\4\name= apps\size=4 size=4 type=taskbar [tray] type=tray [calendar] type=calendar version=old-calendar [statusnotifier] alignment=Right hideApp= showApp=ukui-volume-control-applet-qt,kylin-nm,ukui-sidebar,indicator-china-weather,ukui-flash-disk,Fcitx,sogouimebs-qimpanel,fcitx-qimpanel,explorer.exe,ukui-power-manager-tray,baidu-qimpanel,iflyime-qim,hedronagent,CTJManageTool,evolution,ukui-bluetooth type=statusnotifier [nightmode] type=nightmode [showdesktop] alignment=Right type=showdesktop [taskview] type=taskview [spacer] type=spacer [segmentation] type=segmentation [startbar] alignment=Left type=startbar ukui-panel-3.0.6.4/panel/resources/org.ukui.panel.tray.gschema.xml0000644000175000017500000000166614203402514023440 0ustar fengfeng '' Keybinding Keybinding associated with a custom shortcut. '' Command Command associated with a custom keybinding. '' Name Description associated with a custom keybinding. '' Record Description associated with a custom keybinding. ukui-panel-3.0.6.4/panel/resources/ukui-panel-plugins-revise.sh0000644000175000017500000000011514203402514023035 0ustar fengfeng#!/bin/bash echo "shell file :$0" echo "plugins $1" echo "第二个参数$2" ukui-panel-3.0.6.4/panel/resources/panel-commission.ini0000644000175000017500000000066014204636772021460 0ustar fengfeng;任务栏配置文件 [NightMode] nightmode=show active=true [Hibernate] hibernate=show [Calendar] CalendarVersion=new [ShowInTray] trayname=ukui-volume-control-applet-qt,kylin-nm,ukui-sidebar,indicator-china-weather,ukui-flash-disk,fcitx,sogouimebs-qimpanel,fcitx-qimpanel,explorer.exe,ukui-power-manager-tray,baidu-qimpanel,iflyime-qim,hedronagent,CTJManageTool [IgnoreWindow] ignoreWindow=ukui-menu,ukui-sidebar,ukui-search ukui-panel-3.0.6.4/panel/resources/ukui-panel_tr.ts0000644000175000017500000014406414203402514020620 0ustar fengfeng AddPluginDialog Add Plugins Eklenti Ekle Search: Ara: Add Widget Widget Ekle Close Kapat (only one instance can run at a time) (aynı anda yalnızca bir örnek çalıştırılabilir) CalendarActiveLabel Time and Date Setting Zaman ve Tarih Ayarları Config panel Paneli Ayarla ConfigDialog Dialog ConfigPanelDialog Configure Panel Paneli Ayarla Panel Panel Widgets Widgetler ConfigPanelWidget Configure panel Paneli Ayarla Size Boyut <p>Negative pixel value sets the panel length to that many pixels less than available screen space.</p><p/><p><i>E.g. "Length" set to -100px, screen size is 1000px, then real panel length will be 900 px.</i></p> <p>Negatif piksel değeri, panel uzunluğunu kullanılabilir ekran alanından daha az piksele ayarlar.</p><p/><p><i>E.g. "Length" set to -100px, screen size is 1000px, then real panel length will be 900 px.</i></p> Size: Boyut: Length: Uzunluk: % % px px px px Icon size: Simge Boyutu: Rows: Satırlar: Alignment && position Hizalama & & durum Alignment: Hizalama Left Sol Center Orta Right Sağ Position: Konum: A&uto-hide O&tomatik Gizle Zero means no animation Sıfır, animasyon olmaması anlamına gelir Animation duration: Animasyon süresi: ms ms Zero means no delay Sıfır, gecikme olmadığı anlamına gelir Show with delay: Gecikmeli göster: Visible thin margin for hidden panel Gizli panel için görünür ince kenar boşluğu Don't allow maximized windows go under the panel window Ekranı kaplayan pencerelerin panel penceresinin altına girmesine izin verme Reserve space on display Ekranda rezerv alanı Top of desktop Masaüstünün üstü Left of desktop Masaüstünün Solu Right of desktop Masaüstünün Sağı Bottom of desktop Masaüstünün altı Top of desktop %1 %1 Masaüstünün üstü Left of desktop %1 %1 Masaüstünün solu Right of desktop %1 %1 Masaüstünün sağı Bottom of desktop %1 %1 Masaüstünün altı Top Üst Bottom Alt ConfigPluginsWidget Configure Plugins Eklentileri Yapılandır Note: changes made in this page cannot be reset. Not: bu sayfada yapılan değişiklikler sıfırlanamaz. Move up Yukarı al ... ... Move down Aşağı al Add Ekle Remove Çıkar Configure Yapılandır IndicatorCalendar '<b>'HH:mm:ss'</b><br/><font size="-2">'ddd, d MMM yyyy'<br/>'TT'</font>' MainWindow MainWindow Ana Pencere usb management tool Usb yönetim aracı NightMode nightmode Gece Modu NightModeButton please install new ukui-control-center first Lütfen önce yeni ukui-control-center kurun Turn On NightMode Gece Modunu Aç Set Up NightMode Gece Modunu Ayarla nightmode open Gece Modu Açık nightmode close Gece Modu Kapalı don't contains the keys style-name Anahtarlar stil adını içermiyor please install gtk-theme first ütfen önce gtk-theme yükleyin QClickWidget 弹出 the capacity is empty Kapasite boş blank CD Boş CD QCoreApplication Choose the page to be shown. Gösterilecek sayfayı seçin. [mimetype(s)...] [file | URL] [files | URLs] Available commands: Kullanılabilir komutlar: QObject Power Manager Error Power Manager Hatası QDBusInterface is invalid QDBusInterface geçersiz Power Manager Error (D-BUS call) Power Manager Hatası (D-BUS çağrısı) QuickLaunchAction Error Path Yol Hatası File/URL cannot be opened cause invalid path. Dosya/URL açılamıyor çünkü geçersiz yol. QuickLaunchButton move left Sola al move right Sağa al move to left Sola al move to right Sağa al move to up Yukarı al move to down Aşağı al delete from quicklaunch Hızlı başlattan sil Drop Error Düşme Hatası File/URL '%1' cannot be embedded into QuickLaunch for now Dosya/URL şimdilik Hızlı Başlat'a gömülemiyor ShowDesktop Show Desktop Masaüstünü göster SpacerConfiguration Spacer Settings Boşlık ayarları Space width: Boşluk genişliği: Space type: Boşluk türü: fixed Sabitlendi expandable Genişletilebilir lined Çizgili dotted Noktalı invisible Görünmez StartMenuButton Lock The Screen Ekranı Kilitle Switch The User Kullanıcıyı Değiştir Logout Çıkış Reboot Yeniden Başlat Shutdown Bilgisayarı Kapat TaskView taskviewWindow Önizleme penceresi Show Taskview Görev Görüntüsünü Göster UKUIPanel Set up Panel Paneli Ayarla Show Taskview Görev Görüntüsünü Göster Show Desktop Masaüstünü Göster Show System Monitor Sistem İzleyiciyi Göster Small Küçük Media Medya Medium Orta Large Büyük Adjustment Size Boyut Ayarı Up Üst Bottom Alt Left Sol Right Sağ Adjustment Position Konumu Ayarla Show Nightmode Gecemodunu Göster Lock This Panel Bu Paneli Kilitle About Kylin Ukui Hakkında Remove Panel Paneli Sil Removing a panel can not be undone. Do you want to remove this panel? Panelin silinmesi geri alınamaz. Bu paneli kaldırmak istiyor musunuz? UKUIQuickLaunch Drop Error Bırakma Hatası File/URL '%1' cannot be embedded into QuickLaunch for now Dosya/URL '%1' şimdilik Hızlı Başlat'a gömülemez Drop application icons here Bırakma uygulaması simgeler burada UKUIStartMenuButton Lock The Screen Ekranı Kilitle Switch The User Kullanıcıyı Değiştir Logout Çıkış Reboot Yeniden Başlat Shutdown Bilgisayarı Kapat User Action Kullanıcı Eylemi Sleep or Hibernate Uyku veya Hazırda Bekletme Power Supply Güç kaynağı Lock Screen Ekranı Kilitle Switch User Kullanıcıyı Değiştir Sleep Mode Uyku Modu Hibernate Mode Hazırda Bekletme Modu LogOut Çıkış Restart Yeniden Başlat TimeShutdown Zamanlayıcı anahtarı Power Off Bilgisayarı Kapat UKUITaskButton Application Uygulama To &Desktop Masaüstüne &All Desktops Tüm Masaüstleri Desktop &%1 Masaüstü &%1 &To Current Desktop Mevcut Masaüstüne &Move Oynat Resi&ze Yeniden Boyutlandır Ma&ximize Büyüt Maximize vertically Dikey Büyüt Maximize horizontally Yatay Büyüt &Restore Onar Mi&nimize Küçült Roll down Yuvarlan Roll up Toplan &Layer Katman Always on &top Her zaman üstte &Normal Normal Always on &bottom Her zaman altta &Close &Kapat UKUITaskGroup Group Grup close Kapat UKUITaskWidget Widget close Kapat restore Onar maximaze Büyüt minimize Küçült UKUi::MessageBox UKUi Power Manager Error UKUi Power Manager Hatası Hibernate failed. Hazırda bekletme başarısız oldu. UKUi::NotificationPrivate Notifications Fallback Geribildirim bildirimleri UKUi::PowerManager Hibernate Hazırda Beklet Suspend Beklemeye Al Reboot Yeniden Başlat Shutdown Bilgisayarı Kapat Logout Çıkış UKUi Session Suspend UKUi Oturumu Askıya Alındı Do you want to really suspend your computer?<p>Suspends the computer into a low power state. System state is not preserved if the power is lost. Bilgisayarınızı gerçekten askıya almak istiyor musunuz? Bilgisayarı düşük güç durumuna geçirir. Güç kesilirse sistem durumu korunmaz. UKUi Session Hibernate UKUI Oturumunu Beklemeye Al Do you want to really hibernate your computer?<p>Hibernates the computer into a low power state. System state is preserved if the power is lost. Bilgisayarınızı gerçekten hazırda bekletmek mi istiyorsunuz? Bilgisayarı düşük güç durumuna geçirir. Güç kesilirse sistem durumu korunur. UKUi Session Reboot UKUi Oturumunu Yeniden Başlat Do you want to really restart your computer? All unsaved work will be lost... Bilgisayarınızı gerçekten yeniden başlatmak istiyor musunuz? Kaydedilmemiş tüm işler kaybedilecek ... UKUi Session Shutdown UKUi Oturumu Kapat Do you want to really switch off your computer? All unsaved work will be lost... Bilgisayarınızı gerçekten kapatmak istiyor musunuz? Kaydedilmemiş tüm işler kaybedilecek ... UKUi Session Logout UKUI Oturumundan Çıkış Do you want to really logout? All unsaved work will be lost... Gerçekten çıkış yapmak ister misiniz? Kaydedilmemiş tüm işler kaybedilecek ... UKUi Power Manager Error UKUi Power Manager Hatası Hibernate failed. Hazırda bekletme başarısız oldu. Suspend failed. Askıya alma başarısız oldu. UKUi::ScreenSaver Screen Saver Error Ekran Koruyucu Hatası An error occurred starting screensaver. Syntax error in xdg-screensaver arguments. Ekran koruyucu başlatılırken bir hata oluştu. Xdg-screensaver bağımsız değişkenlerinde sözdizimi hatası. Screen Saver Activation Error Ekran Koruyucu Etkinleştirme Hatası An error occurred starting screensaver. Ensure you have xscreensaver installed and running. Ekran koruyucu başlatılırken bir hata oluştu. Yüklü ve çalışıyor xscreensaver yüklü olduğundan emin olun. An error occurred starting screensaver. Action 'activate' failed. Ensure you have xscreensaver installed and running. Ekran koruyucu başlatılırken bir hata oluştu. İşlem etkinleştirilemedi. Yüklü ve çalışıyor xscreensaver yüklü olduğundan emin olun. An error occurred starting screensaver. Unknown error - undocumented return value from xdg-screensaver: %1. Ekran koruyucu başlatılırken bir hata oluştu. Bilinmeyen hata - xdg-screensaver'dan belgelenmemiş dönüş değeri: %1. Lock Screen Ekranı Kilitle UkuiWebviewDialog Dialog ejectInterface usb has been unplugged safely USB güvenli bir şekilde çıkarıldı usb is occupying unejectable usb reddedilemez işgal ediyor data device has been unloaded veri cihazı kaldırıldı gparted has started Gparted başladı main Use alternate configuration file. Alternatif yapılandırma dosyası kullanın. Configuration file Yapılandırma dosyası ukui-panel-3.0.6.4/panel/resources/ukui-panel_zh_CN.ts0000644000175000017500000014740314203402514021174 0ustar fengfeng BaseDialog Disk test CalendarActiveLabel Time and Date 时间与日期 Time and Date Setting 时间日期设置 Config panel 设置任务栏 ConfigPanelWidget Left Right Bottom DeviceOperation unknown FDClickWidget Eject Unmounted the capacity is empty 负载为空 blank CD 光盘为空 other user device FormateDialog Disk format Formatted successfully! Formatting failed, please unplug the U disk and try again! Format Rom size: Filesystem: Disk name: Completely erase(Time is longer, please confirm!) Cancel Format disk Formatting this volume will erase all data on it. Please back up all retained data before formatting. Do you want to continue? IndicatorCalendar Time and Date 时间与日期 LunarCalendarItem 消防宣传日 志愿者服务日 全国爱眼日 抗战纪念日 LunarCalendarWidget Year Month Today 解析json文件错误! Sun Mon Tue Wed Thur Fri Sat Sunday Monday Tuesday Wednesday Thursday Friday Saturday MainWindow MainWindow usb management tool ukui-flash-disk kindly reminder wrong reminder Please do not pull out the storage device when reading or writing Please do not pull out the CDROM when reading or writing Please do not pull out the SD Card when reading or writing Please do not pull out the USB flash disk when reading or writing Storage device removed telephone device MessageBox OK Cancel NightMode nightmode 夜间模式 NightModeButton please install new ukui-control-center first 请先安装最新的控制面板 Turn On NightMode 夜间模式 Set Up NightMode 设置夜间模式 nightmode opened 夜间模式开启 nightmode closed 夜间模式关闭 night mode open 夜间模式开启 night mode close 夜间模式关闭 nightmode open 夜间模式打开 nightmode close 夜间模式关闭 nightmode open 夜间模式开启 nightmode close 夜间模式关闭 夜间模式关闭 please install gtk-theme first 请先安装gtk主题 QClickWidget 弹出 Unmounted the capacity is empty 负载为空 blank CD 光盘为空 other user device QuickLaunchAction Error Path 路径错误 File/URL cannot be opened cause invalid path. 非法文件路径无法被打开. QuickLaunchButton move left 左移 move right 右移 move to left 左移 move to right 右移 move to up 上移 move to down 下移 delete from quicklaunch 从任务栏取消固定 Drop Error 路径错误 File/URL '%1' cannot be embedded into QuickLaunch for now 路径'%1'无法被添加到快速启动栏 RepairDialogBox Disk test <h4>The system could not recognize the disk contents</h4><p>Check that the disk/drive '%1' is properly connected,make sure the disk is not a read-only disk, and try again.For more information, search for help on read-only files andhow to change read-only files.</p> <h4>The system could not recognize the disk contents</h4><p>Check that the disk/drive is properly connected,make sure the disk is not a read-only disk, and try again.For more information, search for help on read-only files andhow to change read-only files.</p> Format disk Repair RepairProgressBar Disk repair <h3>%1</h3> Attempting a disk repair... Cancel Repair successfully! The repair completed. If the USB flash disk is not mounted, please try formatting the device! ShowDesktop Show Desktop 显示桌面 SpacerConfiguration Spacer Settings Space width: Space type: fixed expandable lined dotted invisible StartMenuButton Lock The Screen 锁定屏幕 Switch The User 切换用户 UKui Menu 开始菜单 UKUI Menu 开始菜单 User Action 用户操作 Sleep or Hibernate 休眠或睡眠 Power Supply 电源 Lock Screen 锁屏 Switch User 切换用户 Logout 注销 Hibernate Mode 休眠 Sleep Mode 睡眠 Restart 重启 TimeShutdown 定时关机 Power Off 关机 Reboot 重启 Shutdown 关机 TaskView taskviewWindow 预览窗口 Show Taskview 显示任务视图 TaskViewButton Show Taskview UKUIPanel Set up Panel 设置任务栏 Show Taskview 显示任务视图按钮 Show Desktop 显示桌面 Show System Monitor 系统监视器 Small 小尺寸 Media 中尺寸 Medium 中尺寸 Large 大尺寸 Adjustment Size 调整大小 Up Bottom Left Right Adjustment Position 调整位置 Hide Panel 隐藏任务栏 Show Nightmode 显示夜间模式按钮 Lock This Panel 锁定任务栏 About Kylin 关于麒麟 Remove Panel Dialog Title Removing a panel can not be undone. Do you want to remove this panel? UKUIStartMenuButton Lock The Screen 锁定屏幕 Switch The User 切换用户 Logout 注销 Reboot 重启计算机 Shutdown 关闭计算机 UKui Menu 开始菜单 User Action 用户操作 Sleep or Hibernate 休眠或睡眠 Power Supply 电源 Lock Screen 锁屏 Switch User 切换用户 Sleep Mode 睡眠 Hibernate Mode 休眠 LogOut 注销 Restart 重启 TimeShutdown 定时关机 Power Off 关机 UKUITaskBar Drop Error 路径错误 File/URL '%1' cannot be embedded into QuickLaunch for now 路径'%1'无法被添加到快速启动栏 UKUITaskButton Application To &Desktop &All Desktops Desktop &%1 &To Current Desktop &Move Resi&ze Ma&ximize Maximize vertically Maximize horizontally &Restore Mi&nimize Roll down Roll up &Layer Always on &top &Normal Always on &bottom &Close &关闭 delete from quicklaunch 从任务栏取消固定 UKUITaskGroup Group delete from taskbar add to taskbar close 关闭 UKUITaskWidget Widget close 关闭 restore 还原 maximaze 最大化 minimize 最小化 above 置顶 clear 取消置顶 UKUi::PowerManager Reboot 重启 Shutdown 关机 Logout 注销 UkuiWebviewDialog Dialog ejectInterface Storage device can be safely unplugged frmLunarCalendarWidget Form 整体样式 红色风格 选中样式 矩形背景 圆形背景 角标背景 图片背景 星期格式 短名称 普通名称 长名称 英文名称 显示农历 gpartedInterface gparted has started,can not eject ok interactiveDialog cdrom is occupying,do you want to eject it sd is occupying,do you want to eject it usb is occupying,do you want to eject it cdrom is occupying sd is occupying usb is occupying cancle yes main Use alternate configuration file. Configuration file ukui-panel set mode panel set option ukui-panel-3.0.6.4/panel/resources/org.ukui.panel.settings.gschema.xml0000644000175000017500000000564514203402514024322 0ustar fengfeng 46 panelsize the size of UKUI Panel 32 IconSize the size of ukui-panel's icon 0 PanelPosition The Position of ukui-panel true show TsskView control taskview show or hide true show TsskView control taskview show or hide 1 show Quicklaunch Lines show Quicklaunch Lines 8 show Apps Number the size of apps number in quicklaunch 1 show Taskbar Lines show Taskbar Lines 1 show Tray Lines show Tray Lines 1 show Panel Lines show Panel Lines 0 show Panel Quicklaunch size show Panel Quicklaunch size 0 show Panel Taskbar size show Panel Taskbar size 0 show Panel Tray size show Panel Tray size true show Statusnotifier button show Statusnotifier button ukui-panel-3.0.6.4/panel/resources/ukui-panel-config.sh0000644000175000017500000000072614203402514021336 0ustar fengfeng#!/bin/bash ## 主要用于ukui3.0->ukui3.1 过渡阶段任务栏的插件配置 echo $1 echo $2 plugin_name=$1 plugin_config=$2 if [ "$plugin_name" = "calendar" ]; then if [ "$plugin_config" = "new" ]; then sed -i 's/CalendarVersion=old/CalendarVersion=new/' ${HOME}/.config/ukui/panel-commission.ini else sed -i 's/CalendarVersion=new/CalendarVersion=old/' ${HOME}/.config/ukui/panel-commission.ini fi elif [ "$plugin_name" = "tray" ]; then echo "tray" fi ukui-panel-3.0.6.4/panel/resources/ukui-panel.desktop0000644000175000017500000000032614203402514021126 0ustar fengfeng[Desktop Entry] Name=ukui-panel comment=Panel Comment[zh_CN]=任务栏 Exec=ukui-panel Terminal=false Type=Application Icon=panel X-UKUI-AutoRestart=true OnlyShowIn=UKUI NoDisplay=true X-UKUI-Autostart-Phase=Panel ukui-panel-3.0.6.4/panel/resources/ukui-panel-reset.sh0000644000175000017500000000127714203402514021215 0ustar fengfeng#!/bin/bash ## 保证任务栏稳定性 ## 在配置文件异常的情况下 使用默认配置文件 grep -nr "plugins" ${HOME}/.config/ukui/panel.conf if [ $? -ne 0 ]; then echo "配置文件异常" rm ${HOME}/.config/ukui/panel.conf cp /usr/share/ukui/panel.conf ${HOME}/.config/ukui/ else echo "配置文件正常" fi plugin_conf="" plugin_conf_backup="" while read line do if [[ $line == *plugin* ]];then echo $line plugin_conf=$line fi done < ${HOME}/.config/ukui/panel.conf while read line do if [[ $line == *plugin* ]];then echo $line plugin_conf_backup=$line fi done < /usr/share/ukui/panel.conf echo $plugin_conf echo $plugin_conf_backup ukui-panel-3.0.6.4/panel/pluginsettings.cpp0000644000175000017500000001350114203402514017231 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2015 LXQt team * Authors: * Paulo Lieuthier * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "pluginsettings.h" #include "pluginsettings_p.h" //#include #include "common/ukuisettings.h" class PluginSettingsPrivate { public: PluginSettingsPrivate(UKUi::Settings* settings, const QString &group) : mSettings(settings) , mOldSettings(settings) , mGroup(group) { } QString prefix() const; inline QString fullPrefix() const { return mGroup + "/" + prefix(); } UKUi::Settings *mSettings; UKUi::SettingsCache mOldSettings; QString mGroup; QStringList mSubGroups; }; QString PluginSettingsPrivate::prefix() const { if (!mSubGroups.empty()) return mSubGroups.join('/'); return QString(); } PluginSettings::PluginSettings(UKUi::Settings* settings, const QString &group, QObject *parent) : QObject(parent) , d_ptr(new PluginSettingsPrivate{settings, group}) { Q_D(PluginSettings); connect(d->mSettings, &UKUi::Settings::settingsChangedFromExternal, this, &PluginSettings::settingsChanged); } QString PluginSettings::group() const { Q_D(const PluginSettings); return d->mGroup; } PluginSettings::~PluginSettings() { } QVariant PluginSettings::value(const QString &key, const QVariant &defaultValue) const { Q_D(const PluginSettings); d->mSettings->beginGroup(d->fullPrefix()); QVariant value = d->mSettings->value(key, defaultValue); d->mSettings->endGroup(); return value; } void PluginSettings::setValue(const QString &key, const QVariant &value) { Q_D(PluginSettings); d->mSettings->beginGroup(d->fullPrefix()); d->mSettings->setValue(key, value); d->mSettings->endGroup(); emit settingsChanged(); } void PluginSettings::remove(const QString &key) { Q_D(PluginSettings); d->mSettings->beginGroup(d->fullPrefix()); d->mSettings->remove(key); d->mSettings->endGroup(); emit settingsChanged(); } bool PluginSettings::contains(const QString &key) const { Q_D(const PluginSettings); d->mSettings->beginGroup(d->fullPrefix()); bool ret = d->mSettings->contains(key); d->mSettings->endGroup(); return ret; } QList > PluginSettings::readArray(const QString& prefix) { Q_D(PluginSettings); d->mSettings->beginGroup(d->fullPrefix()); QList > array; int size = d->mSettings->beginReadArray(prefix); for (int i = 0; i < size; ++i) { d->mSettings->setArrayIndex(i); QMap map; const auto keys = d->mSettings->childKeys(); for (const QString &key : keys) { map[key] = d->mSettings->value(key); } if (array.contains(map)) { continue; } else { array << map; } } d->mSettings->endArray(); d->mSettings->endGroup(); return array; } void PluginSettings::setArray(const QString &prefix, const QList > &hashList) { Q_D(PluginSettings); d->mSettings->beginGroup(d->fullPrefix()); d->mSettings->beginWriteArray(prefix); int size = hashList.size(); for (int i = 0; i < size; ++i) { d->mSettings->setArrayIndex(i); QMapIterator it(hashList.at(i)); while (it.hasNext()) { it.next(); d->mSettings->setValue(it.key(), it.value()); } } d->mSettings->endArray(); d->mSettings->endGroup(); emit settingsChanged(); } void PluginSettings::clear() { Q_D(PluginSettings); d->mSettings->beginGroup(d->mGroup); d->mSettings->clear(); d->mSettings->endGroup(); emit settingsChanged(); } void PluginSettings::sync() { Q_D(PluginSettings); d->mSettings->beginGroup(d->mGroup); d->mSettings->sync(); d->mOldSettings.loadFromSettings(); d->mSettings->endGroup(); emit settingsChanged(); } QStringList PluginSettings::allKeys() const { Q_D(const PluginSettings); d->mSettings->beginGroup(d->fullPrefix()); QStringList keys = d->mSettings->allKeys(); d->mSettings->endGroup(); return keys; } QStringList PluginSettings::childGroups() const { Q_D(const PluginSettings); d->mSettings->beginGroup(d->fullPrefix()); QStringList groups = d->mSettings->childGroups(); d->mSettings->endGroup(); return groups; } void PluginSettings::beginGroup(const QString &subGroup) { Q_D(PluginSettings); d->mSubGroups.append(subGroup); } void PluginSettings::endGroup() { Q_D(PluginSettings); if (!d->mSubGroups.empty()) d->mSubGroups.removeLast(); } void PluginSettings::loadFromCache() { Q_D(PluginSettings); d->mSettings->beginGroup(d->mGroup); d->mOldSettings.loadToSettings(); d->mSettings->endGroup(); } PluginSettings* PluginSettingsFactory::create(UKUi::Settings *settings, const QString &group, QObject *parent/* = nullptr*/) { return new PluginSettings{settings, group, parent}; } ukui-panel-3.0.6.4/panel/CMakeLists.txt0000644000175000017500000001315214204636776016234 0ustar fengfengset(PROJECT ukui-panel) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) add_subdirectory(common) #add_subdirectory(xdg) #add_subdirectory(common_fun) set(PRIV_HEADERS panelpluginsmodel.h ukuipanel.h ukuipanelapplication.h ukuipanelapplication_p.h ukuipanellayout.h plugin.h pluginsettings_p.h ukuipanellimits.h pluginmoveprocessor.h highlight-effect.h ) # using UKUi namespace in the public headers. set(PUB_HEADERS ukuipanelglobals.h pluginsettings.h iukuipanelplugin.h iukuipanel.h comm_func.h common/ukuisettings.h common/ukuiplugininfo.h common/ukuiapplication.h common/ukuisingleapplication.h common/ukuitranslator.h common/ukuigridlayout.h common/ukuiglobals.h common_fun/listengsettings.h common_fun/ukuipanel_infomation.h common_fun/dbus-adaptor.h common_fun/panel_commission.h ukuicontrolstyle.h highlight-effect.cpp customstyle.h ) set(SOURCES main.cpp panelpluginsmodel.cpp windownotifier.cpp ukuipanel.cpp ukuipanelapplication.cpp ukuipanellayout.cpp plugin.cpp pluginsettings.cpp pluginmoveprocessor.cpp ukuipanelpluginconfigdialog.cpp comm_func.cpp common/ukuiplugininfo.cpp common/ukuisettings.cpp common/ukuiapplication.cpp common/ukuisingleapplication.cpp common/ukuitranslator.cpp common/ukuigridlayout.cpp common_fun/listengsettings.cpp common_fun/ukuipanel_infomation.cpp common_fun/dbus-adaptor.cpp common_fun/panel_commission.cpp ukuicontrolstyle.cpp customstyle.cpp ) file(GLOB CONFIG_FILES resources/*.conf resources/*.qss) ############################################ add_definitions(-DCOMPILE_UKUI_PANEL) set(PLUGIN_DESKTOPS_DIR "${CMAKE_INSTALL_FULL_DATAROOTDIR}/ukui/${PROJECT}") add_definitions(-DPLUGIN_DESKTOPS_DIR=\"${PLUGIN_DESKTOPS_DIR}\") if (WITH_SCREENSAVER_FALLBACK) message(STATUS "Building with conversion of deprecated 'screensaver' plugin") add_definitions(-DWITH_SCREENSAVER_FALLBACK "-DUKUI_LOCK_DESKTOP=\"${CMAKE_INSTALL_FULL_DATAROOTDIR}/applications/ukui-lockscreen.desktop\"") endif () project(${PROJECT}) set(QTX_LIBRARIES Qt5::Widgets Qt5::Xml Qt5::DBus) #Translations #ukui_translate_ts(QM_FILES SOURCES # UPDATE_TRANSLATIONS # ${UPDATE_TRANSLATIONS} # SOURCES # ${PUB_HEADERS} # ${PRIV_HEADERS} # ${SOURCES} # ${UI} # INSTALL_DIR # "${UKUI_TRANSLATIONS_DIR}/${PROJECT_NAME}" #) ukui_app_translation_loader(SOURCES ${PROJECT_NAME}) QT5_ADD_DBUS_ADAPTOR(DBUS_ADAPTOR_SRCS common/dbus/org.ukui.SingleApplication.xml common/ukuisingleapplication.h UKUi::SingleApplication ) set_property(SOURCE ${DBUS_INTERFACE_SRCS} ${DBUS_ADAPTOR_SRCS} PROPERTY SKIP_AUTOGEN ON) list(APPEND SOURCES "${DBUS_INTERFACE_SRCS}" "${DBUS_ADAPTOR_SRCS}") add_executable(${PROJECT} ${PUB_HEADERS} ${PRIV_HEADERS} ${QM_FILES} ${SOURCES} ${UI} ) find_package(PkgConfig) pkg_check_modules(GLIB2 REQUIRED glib-2.0) pkg_check_modules(GIO2 REQUIRED gio-2.0) pkg_check_modules(Gsetting REQUIRED gsettings-qt) include_directories(${GLIB2_INCLUDE_DIRS}) include_directories(${GIO2_INCLUDE_DIRS}) include_directories(${Gsetting_INCLUDE_DIRS}) #ADD_DEFINITIONS(-DQT_NO_KEYWORDS) target_link_libraries(${PROJECT} ${LIBRARIES} ${QTX_LIBRARIES} KF5::WindowSystem ${STATIC_PLUGINS} Qt5Xdg ${GLIB2_LIBRARIES} ${GIO2_LIBRARIES} ${Gsetting_LIBRARIES} ) target_compile_definitions(${PROJECT} PRIVATE "UKUI_RELATIVE_SHARE_DIR=\"${UKUI_RELATIVE_SHARE_DIR}\"" #"UKUI_SHARE_DIR=\"${UKUI_SHARE_DIR}\"" "UKUI_RELATIVE_SHARE_TRANSLATIONS_DIR=\"${UKUI_RELATIVE_TRANSLATIONS_DIR}\"" "UKUI_SHARE_TRANSLATIONS_DIR=\"${UKUI_TRANSLATIONS_DIR}\"" "UKUI_GRAPHICS_DIR=\"${UKUI_GRAPHICS_DIR}\"" #"UKUI_ETC_XDG_DIR=\"${UKUI_ETC_XDG_DIR}\"" "UKUI_DATA_DIR=\"${UKUI_DATA_DIR}\"" "UKUI_INSTALL_PREFIX=\"${CMAKE_INSTALL_PREFIX}\"" #"UKUI_VERSION=\"${UKUI_VERSION}\"" #"COMPILE_LIBUKUI" #"QT_USE_QSTRINGBUILDER" #"QT_NO_CAST_FROM_ASCII" #"QT_NO_CAST_TO_ASCII" #"QT_NO_URL_CAST_FROM_STRING" #"QT_NO_CAST_FROM_BYTEARRAY" #"$<$:QT_NO_DEBUG_OUTPUT>" #"$<$:QT_NO_WARNING_OUTPUT>" ) install(TARGETS ${PROJECT} RUNTIME DESTINATION bin) install(FILES ${CONFIG_FILES} DESTINATION ${CMAKE_INSTALL_DATADIR}/ukui) install(FILES ${PUB_HEADERS} DESTINATION include/ukui) install(FILES ../man/ukui-panel.1 DESTINATION "${CMAKE_INSTALL_MANDIR}/man1" COMPONENT Runtime ) install(FILES resources/ukui-panel.desktop DESTINATION "/etc/xdg/autostart/" COMPONENT Runtime ) install(DIRECTORY ./img/ DESTINATION "${PACKAGE_DATA_DIR}/panel/img" ) install(FILES resources/ukui-panel_zh_CN.qm resources/ukui-panel_zh_CN.ts resources/ukui-panel_tr.ts DESTINATION "${PACKAGE_DATA_DIR}/panel/resources" COMPONENT Runtime ) install(FILES resources/org.ukui.panel.settings.gschema.xml DESTINATION "/usr/share/glib-2.0/schemas" COMPONENT Runtime ) install(FILES resources/panel-commission.sh resources/ukui-panel-reset.sh resources/ukui-panel-config.sh DESTINATION "/usr/share/ukui/ukui-panel" COMPONENT Runtime PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ GROUP_WRITE WORLD_READ WORLD_WRITE WORLD_EXECUTE GROUP_EXECUTE GROUP_READ ) install(FILES resources/panel-commission.ini DESTINATION "/usr/share/ukui/ukui-panel" COMPONENT Runtime ) set(PLUGIN panel) include(../cmake/UkuiPluginTranslationTs.cmake) ukui_plugin_translate_ts(${PLUGIN}) ukui-panel-3.0.6.4/panel/translation/0000755000175000017500000000000014203402514016004 5ustar fengfengukui-panel-3.0.6.4/panel/translation/panel_zh_CN.ts0000644000175000017500000001035214203402514020535 0ustar fengfeng UKUIPanel Small 小尺寸 Medium 中尺寸 Large 大尺寸 Adjustment Size 调整大小 Up Bottom Left Right Adjustment Position 调整位置 Hide Panel 隐藏任务栏 Set up Panel 设置任务栏 Show Taskview 显示任务视图按钮 Show Nightmode 显示夜间模式按钮 Show Desktop 显示桌面 Show System Monitor 系统监视器 Lock This Panel 锁定任务栏 About Kylin 关于麒麟 Remove Panel Dialog Title Removing a panel can not be undone. Do you want to remove this panel? main Use alternate configuration file. Configuration file ukui-panel set mode panel set option ukui-panel-3.0.6.4/panel/windownotifier.cpp0000644000175000017500000000425714203402514017231 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2015 LXQt team * Authors: * Palo Kisa * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "windownotifier.h" #include #include void WindowNotifier::observeWindow(QWidget * w) { //installing the same filter object multiple times doesn't harm w->installEventFilter(this); } bool WindowNotifier::eventFilter(QObject * watched, QEvent * event) { QWidget * widget = qobject_cast(watched); //we're observing only QWidgetw auto it = std::lower_bound(mShownWindows.begin(), mShownWindows.end(), widget); switch (event->type()) { case QEvent::Close: watched->removeEventFilter(this); //no break case QEvent::Hide: Q_ASSERT(mShownWindows.end() != it); // there perhaps cause coredump if (mShownWindows.end() != it) mShownWindows.erase(it); if (mShownWindows.isEmpty()) emit lastHidden(); break; case QEvent::Show: { const bool first_shown = mShownWindows.isEmpty(); mShownWindows.insert(it, widget); //we keep the mShownWindows sorted if (first_shown) emit firstShown(); } default: break; } return false; } ukui-panel-3.0.6.4/panel/comm_func.cpp0000644000175000017500000005027314203402514016127 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2012 Razor team * Authors: * Alexander Sokoloff * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "comm_func.h" #ifndef _GNU_SOURCE #define _GNU_SOURCE //for strcasestr #endif #include #include #include #include #include #include #include #include #include #include // for opendir(), readdir(), closedir() #include // for stat() #include #include #include #include #include #include #define BUF_LEN 128 #define BUFF_SIZE (512) bool getRunCmdOutput(const char *command, char *output, int max_size) { FILE *stream; if ((stream = popen(command, "r" )) == NULL) return false; if (fread(output, sizeof(char), max_size, stream) <= 0) { pclose(stream); return false; } pclose(stream); return true; } void startChildApp(const char *app_exe,char *argv_exec[]) { /* exec command */ pid_t child_pid; child_pid = fork(); if (child_pid < 0) { perror("fork"); } else if (child_pid == 0) { /* child process */ pid_t grandchild_pid; grandchild_pid = fork(); if (grandchild_pid < 0) { perror("fork"); _exit(1); } else if (grandchild_pid == 0) { /* grandchild process */ execvp(app_exe, argv_exec); perror("execvp"); _exit(1); } else { _exit(0); } } else { waitpid(child_pid,NULL,0); } } //QString->char * void save_q_string_2_m_string(QString q_string, char **m_buf) { int len; std::string tmp_str; char *m_buf_tmp; tmp_str = q_string.toStdString(); len = tmp_str.length() + 1; if ((m_buf_tmp = (char *)malloc(len)) == NULL) return; memset(m_buf_tmp, 0, len); memcpy(m_buf_tmp, tmp_str.c_str(), len); if (*m_buf) free(*m_buf); *m_buf = m_buf_tmp; } //QString 转wchar_t* const wchar_t* qstring2wchar_t(QString str) { //create variable to hold converted QString wchar_t *someVar=new wchar_t[str.size()+1]; //copy QString to allocated variable str.toWCharArray(someVar); //set last caharacter to null terminator someVar[str.size()]=L'\0'; //create another variable wchar_t *anotherVar=new wchar_t[str.size()+1]; //copy above allocated variable to this one wcscpy(anotherVar, someVar); // release resource if (someVar) { delete[] someVar; } return anotherVar; } QString wchar2string(const wchar_t* wchar_str) { return QString::fromWCharArray(wchar_str); } //.时间戳转格式化 QString time_2_string(time_t t) { QString tmp; struct tm *p; p=gmtime(&t); char s[100]={0}; strftime(s, sizeof(s), "%Y-%m-%d ", p); // printf("%d: %s\n", (int)t, s); tmp = s; return tmp; } //格式化转时间戳 long int string_2_time(char *str_time) { struct tm stm; int iY, iM, iD, iH, iMin, iS; memset(&stm,0,sizeof(stm)); iY = atoi(str_time); iM = atoi(str_time+5); iD = atoi(str_time+8); iH = atoi(str_time+11); iMin = atoi(str_time+14); iS = atoi(str_time+17); stm.tm_year=iY-1900; stm.tm_mon=iM-1; stm.tm_mday=iD; stm.tm_hour=iH; stm.tm_min=iMin; stm.tm_sec=iS; /*printf("%d-%0d-%0d %0d:%0d:%0d\n", iY, iM, iD, iH, iMin, iS);*/ return mktime(&stm); } bool getReadFileContent(const char *file_path, char *output, int max_size) { FILE *stream; if ((stream = fopen(file_path, "r" )) == NULL) return false; if (fread(output, sizeof(char), max_size, stream) <= 0) { fclose(stream); return false; } fclose(stream); return true; } char* getOsVersion() { static char buf[BUF_LEN]={0}; char os_buf[BUF_LEN]={0}; char platform_buf[BUF_LEN]={0}; bool rst; char *cmd = "cat /etc/os-release | grep -i PRETTY_NAME | awk -F'=' '{print $2}'"; rst = getRunCmdOutput(cmd, os_buf, BUF_LEN); if(rst) { char *cmd_platform = "uname -i"; rst = getRunCmdOutput(cmd_platform, platform_buf, BUF_LEN); } if(rst) { int len = strlen(os_buf); os_buf[len-1] = '\0'; sprintf(buf, "%s_%s", os_buf,platform_buf); } buf[strlen(buf)-1] = '\0'; for(int i=0;i2){ for(int i=0;i= QT_VERSION_CHECK(5,7,0)) for(QFileInfo file_info:qAsConst(info_list)){ #endif if (file_info.isDir()) { removefilesindir(file_info.absoluteFilePath()); } else if (file_info.isFile()) { QFile file(file_info.absoluteFilePath()); // qDebug() << "remove file : " << file_info.absoluteFilePath(); file.remove(); } } QDir temp_dir; temp_dir.rmdir(path) ; // qDebug() << "remove empty dir : " << path; } //https://www.devbean.net/2016/08/goodbye-q_foreach/ //fileInfoList 不让被修改,转换成const bool removeDir(const QString & dirName) { bool result = true; QDir dir(dirName); if (dir.exists(dirName)) { QFileInfoList fileInfoList = dir.entryInfoList(QDir::NoDotAndDotDot | QDir::System | QDir::Hidden | QDir::AllDirs | QDir::Files, QDir::DirsFirst); #if (QT_VERSION < QT_VERSION_CHECK(5,7,0)) for(int i=0;i= QT_VERSION_CHECK(5,7,0)) for(QFileInfo info:qAsConst(fileInfoList)) { #endif if (info.isDir()) { result = removeDir(info.absoluteFilePath()); } else { result = QFile::remove(info.absoluteFilePath()); } if (!result) { return result; } } result = dir.rmdir(dirName); } return result; } bool createDir(const char *sPathName) { char DirName[256]; strcpy(DirName, sPathName); int i,len = strlen(DirName); if(DirName[len-1]!='/') strcat(DirName, "/"); len = strlen(DirName); for(i=1;iexists(toDir); if(!dirExist) createDir->mkdir(toDir); QFile *createFile = new QFile; bool fileExist = createFile->exists(toDir+fileName); if (fileExist){ if(coverFileIfExist){ createFile->remove(toDir+fileName); } }//end if free(createDir); free(createFile); if(!QFile::copy(sourceDir+fileName, toDir+fileName)) { return false; } return true; } /** qCopyDirectory -- 拷贝目录 fromDir : 源目录 toDir : 目标目录 bCoverIfFileExists : ture:同名时覆盖 false:同名时返回false,终止拷贝 返回: ture拷贝成功 false:拷贝未完成 */ bool qCopyDirectory(const QDir& fromDir, const QDir& toDir, bool bCoverIfFileExists) { QDir formDir_ = fromDir; QDir toDir_ = toDir; if(!toDir_.exists()) { if(!toDir_.mkdir(toDir_.absolutePath())) { return false; } } QFileInfoList fileInfoList = formDir_.entryInfoList(); #if (QT_VERSION < QT_VERSION_CHECK(5,7,0)) for(int i=0;i= QT_VERSION_CHECK(5,7,0)) for(QFileInfo fileInfo:qAsConst(fileInfoList)){ #endif if(fileInfo.fileName() == "." || fileInfo.fileName() == "..") continue; //拷贝子目录 if(fileInfo.isDir()) { //递归调用拷贝 if(!qCopyDirectory(QDir(fileInfo.filePath()), QDir(toDir_.filePath(fileInfo.fileName())),bCoverIfFileExists)) { return false; } } //拷贝子文件 else { if(bCoverIfFileExists && toDir_.exists(fileInfo.fileName())) { toDir_.remove(fileInfo.fileName()); } if(!QFile::copy(fileInfo.filePath(), toDir_.filePath(fileInfo.fileName()))) { return false; } } } return true; } //是不是数字 static int IsNumeric(const char* ccharptr_CharacterList) { for ( ; *ccharptr_CharacterList; ccharptr_CharacterList++) if (*ccharptr_CharacterList < '0' || *ccharptr_CharacterList > '9') return 0; // false return 1; // true } /*! * \brief getPidByName * \param the name of process * \return success: the pid of the process failed: -1(the process is not exist) -2(access /proc error) */ pid_t getPidByName(const char* processName) { QDir procDir("/proc/"); int pid = 0; bool findPid = false; QStringList dirLists = procDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot); #if (QT_VERSION < QT_VERSION_CHECK(5,7,0)) for(int i=0;i= QT_VERSION_CHECK(5,7,0)) for(auto & dir : qAsConst(dirLists)) { #endif bool ok; pid = dir.toInt(&ok, 10); if(ok == false) continue; QFile procFile("/proc/" + dir + "/status"); if(!procFile.open(QIODevice::ReadOnly | QIODevice::Text)) { fprintf(stderr, "read proc status failed\n"); continue; } QTextStream in(&procFile); bool findName = false; QString line = in.readLine(); while(!line.isNull()) { QStringList strs = line.split('\t'); if(!findName && strs.size() > 1 && strs.at(0) == "Name:"){ if(strs.at(1) != QString(processName)) break; else findName = true; } if(strs.size() > 1 && strs.at(0) == "State:") { if(strs.at(1).split(' ').at(0)!="Z") findPid = true; else break; } line = in.readLine(); } procFile.close(); if(findPid) break; } fprintf(stderr, "%s:%d\n", processName, pid); return pid; } /// \brief get_total_mem 获取总的内存大小 /// /// \return int get_total_mem() { const char *file = "/proc/meminfo"; char line_buff[128] = {0}; FILE *fp = NULL; char p_name[32] = {0}; unsigned int total_mem; if((fp = fopen(file, "r")) == NULL) return -1; fgets(line_buff, sizeof(line_buff), fp); sscanf(line_buff, "%s %u", p_name, &total_mem); //printf("%s: %u\n", p_name, total_mem); fclose(fp); return total_mem; } /// \brief get_process_mem 获取进程占用的内存 /// /// \param pid 进程ID /// /// \return 进程占用的内存 int get_process_mem(pid_t pid) { char file[64] = {0}; FILE *fp = NULL; char p_name[32] = {0}; char line_buff[128] = {0}; unsigned int process_mem; sprintf(file, "/proc/%d/status", (unsigned int)pid); if((fp = fopen(file, "r")) == NULL) return -1; for(int i = 0; i< 20; i++) fgets(line_buff, sizeof(line_buff), fp); fgets(line_buff, sizeof(line_buff), fp); sscanf(line_buff, "%s %u", p_name, &process_mem); //printf("%s: %u\n", p_name, process_mem); fclose(fp); return process_mem; } /// \brief get_total_cpu_accurancy 获取总的CPU使用量 /// /// \return int get_total_cpu_accurancy() { const char* file = "/proc/stat"; FILE *fp = NULL; char line_buff[512] = {0}; char str[32] = {0}; char *pch = NULL; int num[10] = {0}; int sum = 0, i = 0; if((fp = fopen(file, "r")) == NULL) return -1; fgets(line_buff, sizeof(line_buff), fp); pch = strtok(line_buff, " "); while(pch != NULL) { sprintf(str, "%s", pch); if(IsNumeric(str)) num[i++] = atoi(str); pch = strtok(NULL, " "); } for(i = 0; i<9; i++) sum += num[i]; //printf("%d\n", sum); fclose(fp); return sum; } /// \brief get_process_cpu_accurancy 获取进程的CPU使用量 /// /// \param pid 进程ID /// /// \return int get_process_cpu_accurancy(pid_t pid) { char file[64] = {0}; FILE *fp = NULL; char buff[512] = {0}; char str[32] = {0}; char *pch = NULL; int i = 0, sum = 0; int num[4] = {0}; sprintf(file, "/proc/%d/stat", pid); if((fp = fopen(file, "r")) == NULL) return -1; fgets(buff, sizeof(buff), fp); pch = strtok(buff, " "); while(pch != NULL) { i++; if(i>=14 && i<=17) { sprintf(str, "%s", pch); num[i-14] = atoi(str); } pch = strtok(NULL, " "); } for(i = 0; i<4; i++) { printf("%d,", num[i]); sum += num[i]; } printf("\n"); //printf("%d\n", sum); fclose(fp); return sum; } /// \brief get_cpu_num 获取逻辑CPU个数 /// /// \return int get_cpu_num() { const char *file = "/proc/cpuinfo"; FILE *fp = NULL; char line_buff[128] = {0}; int num = 0; if((fp = fopen(file, "r")) == NULL) return -1; while(fgets(line_buff, sizeof(line_buff), fp) != NULL) { if(strstr(line_buff, "processor") != NULL) { //sscanf(line_buff, "%s %s : %d", tmp, tmp, &cores_num); //return cores_num; num++; } } fclose(fp); return num; } /// \brief get_pmem 获取进程的内存占用率 /// /// \param pid 进程ID /// /// \return 成功,返回内存占用率;失败,返回-1 float get_pmem(pid_t pid) { int p_mem = get_process_mem(pid); int t_mem = get_total_mem(); if(p_mem < 0 || t_mem < 0) return -1; return 100.0 * p_mem / t_mem; } /// \brief get_pcpu 获取进程CPU占用率 /// /// \param pid 进程ID /// /// \return 成功,返回CPU占用率;失败,返回-1 float get_pcpu(pid_t pid) { int process_cpu1, process_cpu2; int total_cpu1, total_cpu2; int cpu_num = get_cpu_num(); if(cpu_num < 0) return -1; process_cpu1 = get_process_cpu_accurancy(pid); total_cpu1 = get_total_cpu_accurancy(); if(process_cpu1 < 0 || total_cpu1 < 0) return -1; usleep(1000000); process_cpu2 = get_process_cpu_accurancy(pid); total_cpu2 = get_total_cpu_accurancy(); if(process_cpu2 < 0 || total_cpu2 < 0) return -1; return 100.0 * cpu_num * (process_cpu2 - process_cpu1) / (total_cpu2 - total_cpu1); } ukui-panel-3.0.6.4/panel/iukuipanelplugin.h0000644000175000017500000002117114203402514017206 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2012 Razor team * Authors: * Alexander Sokoloff * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef IUKUIPANELPLUGIN_H #define IUKUIPANELPLUGIN_H #include #include "iukuipanel.h" #include "ukuipanelglobals.h" #include /** UKUi panel plugins are standalone sharedlibraries (*.so) located in PLUGIN_DIR (define provided by CMakeLists.txt). Plugin for the panel is a library written in C++. One more necessary thing is a .desktop file describing this plugin. The same may be additional files, like translations. Themselves plugins will be installed to /usr/local/lib/ukui-panel or /usr/lib/ukui-panel (dependent on cmake option -DCMAKE_INSTALL_PREFIX). Desktop files are installed to /usr/local/share/ukui/ukui-panel, translations to /usr/local/share/ukui/ukui-panel/PLUGIN_NAME. **/ class QDialog; class PluginSettings; namespace UKUi { class PluginInfo; } struct UKUI_PANEL_API IUKUIPanelPluginStartupInfo { IUKUIPanel *ukuiPanel; PluginSettings *settings; const UKUi::PluginInfo *desktopFile; }; /** \brief Base abstract class for UKUi panel widgets/plugins. All plugins *must* be inherited from this one. This class provides some basic API and inherited/implemented plugins GUIs will be responsible on the functionality itself. **/ class UKUI_PANEL_API IUKUIPanelPlugin { public: /** This enum describes the properties of a plugin. **/ enum Flag { NoFlags = 0, ///< It does not have any properties set. PreferRightAlignment = 1, /**< The plugin prefers right alignment (for example the clock plugin); otherwise the plugin prefers left alignment (like main menu). This flag is used only at the first start, later positions of all plugins are saved in a config, and this saved information is used. */ HaveConfigDialog = 2, ///< The plugin have a configuration dialog. SingleInstance = 4, ///< The plugin allows only one instance to run. NeedsHandle = 8 ///< The plugin needs a handle for the context menu }; Q_DECLARE_FLAGS(Flags, Flag) /** This enum describes the reason the plugin was activated. **/ enum ActivationReason { Unknown = 0, ///< Unknown reason DoubleClick = 2, ///< The plugin entry was double clicked Trigger = 3, ///< The plugin was clicked MiddleClick = 4 ///< The plugin was clicked with the middle mouse button }; enum CalendarShowMode { lunarSunday = 0,//show lunar and first day a week is sunday lunarMonday = 1,//show lunar and first day a week is monday solarSunday = 2,//show solar and first day a week is sunday solarMonday = 3,//show solar and first day a week is monday defaultMode = 0xff }; /** Constructs an IUKUIPanelPlugin object with the given startupInfo. You do not have to worry about the startupInfo parameters, IUKUIPanelPlugin processes the parameters itself. **/ IUKUIPanelPlugin(const IUKUIPanelPluginStartupInfo &startupInfo): mSettings(startupInfo.settings), mPanel(startupInfo.ukuiPanel), mDesktopFile(startupInfo.desktopFile) {} /** Destroys the object. **/ virtual ~IUKUIPanelPlugin() {} /** Returns the plugin flags. The base class implementation returns a NoFlags. **/ virtual Flags flags() const { return NoFlags; } /** Returns the string that is used in the theme QSS file. If you return "WorldClock" string, theme author may write something like `#WorldClock { border: 1px solid red; }` to set a custom border for your plugin. **/ virtual QString themeId() const = 0; /** From the user's point of view, your plugin is some visual widget on the panel. This function returns a pointer to it. This method is called only once, so you are free to return the pointer on a class member, or create the widget on the fly. **/ virtual QWidget *widget() = 0; /** Returns the plugin settings dialog. Reimplement this function if your plugin has it. The panel does not take ownership of the dialog, it is probably a good idea to set Qt::WA_DeleteOnClose attribute for the dialog. The default implementation returns 0, no dialog; Note that the flags method has to return HaveConfigDialog flag. To save the settings you should use a ready-to-use IUKUIPanelPlugin::settings() object. **/ virtual QDialog *configureDialog() { return 0; } /** This function is called when values are changed in the plugin settings. Reimplement this function to your plugin corresponded the new settings. The default implementation do nothing. **/ virtual void settingsChanged() {} /** This function is called when the user activates the plugin. reason specifies the reason for activation. IUKUIPanelPlugin::ActivationReason enumerates the various reasons. The default implementation do nothing. **/ virtual void activated(ActivationReason reason) {} /** This function is called when the panel geometry or lines count are changed. The default implementation do nothing. **/ virtual void realign() {} /** Returns the panel object. **/ IUKUIPanel *panel() const { return mPanel; } PluginSettings *settings() const { return mSettings; } const UKUi::PluginInfo *desktopFile() const { return mDesktopFile; } /** Helper functions for calculating global screen position of some popup window with windowSize size. If you need to show some popup window, you can use it, to get global screen position for the new window. **/ virtual QRect calculatePopupWindowPos(const QSize &windowSize) { return mPanel->calculatePopupWindowPos(this, windowSize); } /*! * \brief By calling this function plugin notifies the panel about showing a (standalone) window/menu. * * \param w the shown window * */ inline void willShowWindow(QWidget * w) { mPanel->willShowWindow(w); } /*! * \brief By calling this function, a plugin notifies the panel about change of it's "static" * configuration * * \sa isSeparate(), isExpandable */ inline void pluginFlagsChanged() { mPanel->pluginFlagsChanged(this); } virtual bool isSeparate() const { return false; } virtual bool isExpandable() const { return false; } private: PluginSettings *mSettings; IUKUIPanel *mPanel; const UKUi::PluginInfo *mDesktopFile; }; Q_DECLARE_OPERATORS_FOR_FLAGS(IUKUIPanelPlugin::Flags) /** Every plugin must have the IUKUIPanelPluginLibrary loader. You should only reimplement the instance() method which should return your plugin. Example: @code class UKUiClockPluginLibrary: public QObject, public IUKUIPanelPluginLibrary { Q_OBJECT Q_PLUGIN_METADATA(IID "ukui.org/Panel/PluginInterface/3.0") Q_INTERFACES(IUKUIPanelPluginLibrary) public: IUKUIPanelPlugin *instance(const IUKUIPanelPluginStartupInfo &startupInfo) { return new UKUiClock(startupInfo);} }; @endcode **/ class UKUI_PANEL_API IUKUIPanelPluginLibrary { public: /** Destroys the IUKUIPanelPluginLibrary object. **/ virtual ~IUKUIPanelPluginLibrary() {} /** Returns the root component object of the plugin. When the library is finally unloaded, the root component will automatically be deleted. **/ virtual IUKUIPanelPlugin* instance(const IUKUIPanelPluginStartupInfo &startupInfo) const = 0; }; Q_DECLARE_INTERFACE(IUKUIPanelPluginLibrary, "ukui.org/Panel/PluginInterface/3.0") #endif // IUKUIPANELPLUGIN_H ukui-panel-3.0.6.4/panel/comm_func.h0000644000175000017500000000425014203402514015566 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2012 Razor team * Authors: * Alexander Sokoloff * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef _COMM_FUNC_H_ #define _COMM_FUNC_H_ //放公共功能函数 #include #include #include #include #include #include bool getRunCmdOutput(const char *command, char *output, int max_size); bool getReadFileContent(const char *file_path, char *output, int max_size); bool readSystemInfo(); bool isARM(); char* get_machine_id(); char* getOsVersion(); void startChildApp(const char *app_exe,char *argv_exec[]); const wchar_t* qstring2wchar_t(QString str); QString wchar2string(const wchar_t* wchar_str); void save_q_string_2_m_string(QString q_string, char **m_buf); QString time_2_string(time_t t); long int string_2_time(char *str_time); void deleteDirectory(QFileInfo fileList); void removefilesindir(const QString& path); bool removeDir(const QString & dirName); bool createDir(const char *sPathName); bool copyFileToPath(QString sourceDir ,QString toDir, QString copyFileToPath, bool coverFileIfExist); bool qCopyDirectory(const QDir& fromDir, const QDir& toDir, bool bCoverIfFileExists); char *getLoginCookie(char *userid); int getsrand(); int getPidByName(const char* pName); float get_pmem(pid_t pid); float get_pcpu(pid_t pid); #endif ukui-panel-3.0.6.4/panel/ukuipanelpluginconfigdialog.h0000644000175000017500000000370214203402514021403 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2011 Razor team * Authors: * Alexander Sokoloff * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef UKUIPANELPLUGINCONFIGDIALOG_H #define UKUIPANELPLUGINCONFIGDIALOG_H #include #include #include "ukuipanelglobals.h" #include "pluginsettings.h" class QComboBox; class UKUI_PANEL_API UKUIPanelPluginConfigDialog : public QDialog { Q_OBJECT public: explicit UKUIPanelPluginConfigDialog(PluginSettings &settings, QWidget *parent = nullptr); explicit UKUIPanelPluginConfigDialog(PluginSettings *settings, QWidget *parent = nullptr) : UKUIPanelPluginConfigDialog(*settings, parent) {} virtual ~UKUIPanelPluginConfigDialog(); PluginSettings &settings() const; protected slots: /* Saves settings in conf file. */ virtual void loadSettings() = 0; virtual void dialogButtonsAction(QAbstractButton *btn); protected: void setComboboxIndexByData(QComboBox *comboBox, const QVariant &data, int defaultIndex = 0) const; private: PluginSettings &mSettings; }; #endif // UKUIPANELPLUGINCONFIGDIALOG_H ukui-panel-3.0.6.4/panel/highlight-effect.h0000644000175000017500000000540114203402514017020 0ustar fengfeng/* * Qt5-UKUI's Library * * Copyright (C) 2020, Tianjin KYLIN Information Technology Co., Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this library. If not, see . * * Authors: Yue Lan * */ #ifndef HIGHLIGHTEFFECT_H #define HIGHLIGHTEFFECT_H #include #include class QAbstractItemView; class QAbstractButton; class QMenu; class HighLightEffect : public QObject { Q_OBJECT public: enum EffectMode { HighlightOnly, BothDefaultAndHighlit }; Q_ENUM(EffectMode) /*! * \brief setSkipEffect * \param w * \param skip * \details * in ukui-style, some widget such as menu will be set use highlight * icon effect automatically, * but we might not want to compose a special pure color image. * This function is use to skip the effect. */ static void setSkipEffect(QWidget *w, bool skip = true); static bool isPixmapPureColor(const QPixmap &pixmap); static bool setMenuIconHighlightEffect(QMenu *menu, bool set = true, EffectMode mode = HighlightOnly); static bool setViewItemIconHighlightEffect(QAbstractItemView *view, bool set = true, EffectMode mode = HighlightOnly); static bool setButtonIconHighlightEffect(QAbstractButton *button, bool set = true, EffectMode mode = HighlightOnly); static bool isWidgetIconUseHighlightEffect(const QWidget *w); static void setSymoblicColor(const QColor &color); static void setWidgetIconFillSymbolicColor(QWidget *widget, bool fill); static const QColor getCurrentSymbolicColor(); static QPixmap generatePixmap(const QPixmap &pixmap, const QStyleOption *option, const QWidget *widget = nullptr, bool force = false, EffectMode mode = HighlightOnly); static QPixmap filledSymbolicColoredPixmap(const QPixmap &source, const QColor &baseColor); static QPixmap drawSymbolicColoredPixmap(const QPixmap &source); static QIcon drawSymbolicColoredIcon(const QIcon &source); private: explicit HighLightEffect(QObject *parent = nullptr); }; #endif // HIGHLIGHTEFFECT_H ukui-panel-3.0.6.4/panel/plugin.h0000644000175000017500000000736214203402514015125 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2011 Razor team * Authors: * Alexander Sokoloff * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef PLUGIN_H #define PLUGIN_H #include #include #include //#include //#include #include "common/ukuisettings.h" #include "common/ukuiplugininfo.h" #include "iukuipanel.h" #include "ukuipanelglobals.h" #include "pluginsettings.h" class QPluginLoader; class QSettings; class IUKUIPanelPlugin; class IUKUIPanelPluginLibrary; class UKUIPanel; class QMenu; class UKUI_PANEL_API Plugin : public QFrame { Q_OBJECT Q_PROPERTY(QColor moveMarkerColor READ moveMarkerColor WRITE setMoveMarkerColor) public: enum Alignment { AlignLeft, AlignRight }; explicit Plugin(const UKUi::PluginInfo &desktopFile, UKUi::Settings *settings, const QString &settingsGroup, UKUIPanel *panel); ~Plugin(); bool isLoaded() const { return mPlugin != 0; } Alignment alignment() const { return mAlignment; } void setAlignment(Alignment alignment); QString settingsGroup() const { return mSettings->group(); } void saveSettings(); QMenu* popupMenu() const; const IUKUIPanelPlugin * iPlugin() const { return mPlugin; } const UKUi::PluginInfo desktopFile() const { return mDesktopFile; } bool isSeparate() const; bool isExpandable() const; QWidget *widget() { return mPluginWidget; } QString name() const { return mName; } virtual bool eventFilter(QObject * watched, QEvent * event); // For QSS properties .................. static QColor moveMarkerColor() { return mMoveMarkerColor; } static void setMoveMarkerColor(QColor color) { mMoveMarkerColor = color; } public slots: void realign(); void showConfigureDialog(); void requestRemove(); signals: void startMove(); void remove(); /*! * \brief Signal emitted when this widget or some of its children * get the DragLeave event delivered. */ void dragLeft(); protected: void contextMenuEvent(QContextMenuEvent *event); void mousePressEvent(QMouseEvent *event); void mouseDoubleClickEvent(QMouseEvent *event); void showEvent(QShowEvent *event); private: bool loadLib(IUKUIPanelPluginLibrary const * pluginLib); bool loadModule(const QString &libraryName); IUKUIPanelPluginLibrary const * findStaticPlugin(const QString &libraryName); void watchWidgets(QObject * const widget); void unwatchWidgets(QObject * const widget); const UKUi::PluginInfo mDesktopFile; QPluginLoader *mPluginLoader; IUKUIPanelPlugin *mPlugin; QWidget *mPluginWidget; Alignment mAlignment; PluginSettings *mSettings; UKUIPanel *mPanel; static QColor mMoveMarkerColor; QString mName; QPointer mConfigDialog; //!< plugin's config dialog (if any) private slots: void settingsChanged(); }; #endif // PLUGIN_H ukui-panel-3.0.6.4/panel/main.cpp0000644000175000017500000001164514203402514015105 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2011 Razor team * Authors: * Alexander Sokoloff * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "ukuipanelapplication.h" #include #include #include #include #include #include #include #include #include #include #include #include /*! The ukui-panel is the panel of UKUI. Usage: ukui-panel [CONFIG_ID] CONFIG_ID Section name in config file ~/.config/ukui/panel.conf (default main) */ void messageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg) { QByteArray localMsg = msg.toLocal8Bit(); QByteArray currentTime = QTime::currentTime().toString().toLocal8Bit(); QString logFilePath = QStandardPaths::writableLocation(QStandardPaths::TempLocation) + "/ukui-panel.log"; bool showDebug = true; if (!QFile::exists(logFilePath)) { showDebug = false; } FILE *log_file = nullptr; if (showDebug) { log_file = fopen(logFilePath.toLocal8Bit().constData(), "a+"); } const char *file = context.file ? context.file : ""; const char *function = context.function ? context.function : ""; switch (type) { case QtDebugMsg: if (!log_file) { break; } fprintf(log_file, "Debug: %s: %s (%s:%u, %s)\n", currentTime.constData(), localMsg.constData(), file, context.line, function); break; case QtInfoMsg: fprintf(log_file? log_file: stdout, "Info: %s: %s (%s:%u, %s)\n", currentTime.constData(), localMsg.constData(), file, context.line, function); break; case QtWarningMsg: fprintf(log_file? log_file: stderr, "Warning: %s: %s (%s:%u, %s)\n", currentTime.constData(), localMsg.constData(), file, context.line, function); break; case QtCriticalMsg: fprintf(log_file? log_file: stderr, "Critical: %s: %s (%s:%u, %s)\n", currentTime.constData(), localMsg.constData(), file, context.line, function); break; case QtFatalMsg: fprintf(log_file? log_file: stderr, "Fatal: %s: %s (%s:%u, %s)\n", currentTime.constData(), localMsg.constData(), file, context.line, function); break; } if (log_file) fclose(log_file); } int main(int argc, char *argv[]) { initUkuiLog4qt("ukui-panel"); qDebug()<<"Main :: ukui-panel start"<= QT_VERSION_CHECK(5, 14, 0)) QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough); #endif UKUIPanelApplication app(argc, argv); qDebug()<<"Main :: UKUIPanelApplication finished"< * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include #include "ukuipanelapplication.h" #include "ukuipanelapplication_p.h" #include "ukuipanel.h" //#include #include "common/ukuisettings.h" #include #include #include #include #include #include #include #include "comm_func.h" #define CONFIG_FILE_BACKUP "/usr/share/ukui/panel.conf" #define CONFIG_FILE_LOCAL ".config/ukui/panel.conf" UKUIPanelApplicationPrivate::UKUIPanelApplicationPrivate(UKUIPanelApplication *q) : mSettings(0), q_ptr(q) { } IUKUIPanel::Position UKUIPanelApplicationPrivate::computeNewPanelPosition(const UKUIPanel *p, const int screenNum) { //#define Q_D(Class) Class##Private * const d = d_func() //#define Q_Q(Class) Class * const q = q_func() Q_Q(UKUIPanelApplication); QVector screenPositions(4, false); // false means not occupied for (int i = 0; i < q->mPanels.size(); ++i) { if (p != q->mPanels.at(i)) { // We are not the newly added one if (screenNum == q->mPanels.at(i)->screenNum()) { // Panels on the same screen int p = static_cast (q->mPanels.at(i)->position()); screenPositions[p] = true; // occupied } } } int availablePosition = 0; for (int i = 0; i < 4; ++i) { // Bottom, Top, Left, Right if (!screenPositions[i]) { availablePosition = i; break; } } return static_cast (availablePosition); } UKUIPanelApplication::UKUIPanelApplication(int& argc, char** argv) : UKUi::Application(argc, argv, true), d_ptr(new UKUIPanelApplicationPrivate(this)) { translator(); // bind to SIGTERM siganl to exit with code 15 signal(SIGTERM, sigtermHandler); Q_D(UKUIPanelApplication); QCoreApplication::setApplicationName(QLatin1String("ukui-panel")); const QString VERINFO = QStringLiteral(UKUI_PANEL_VERSION "\nlibukui " "" "\nQt " QT_VERSION_STR); QCoreApplication::setApplicationVersion(VERINFO); QCommandLineParser parser; parser.setApplicationDescription(QLatin1String("UKUi Panel")); parser.addHelpOption(); parser.addVersionOption(); //添加其他参数 QCommandLineOption configFileOption(QStringList() << QLatin1String("c") << QLatin1String("config") << QLatin1String("configfile"), QCoreApplication::translate("main", "Use alternate configuration file."), QCoreApplication::translate("main", "Configuration file")); parser.addOption(configFileOption); QCommandLineOption panelResetOption(QStringList() << QLatin1String("r") << QLatin1String("reset") << QLatin1String("panel reset"), QCoreApplication::translate("main", "ukui-panel set mode "), QCoreApplication::translate("main", "panel set option")); parser.addOption(panelResetOption); parser.process(*this); const QString configFile = parser.value(configFileOption); if (configFile.isEmpty()) { QString defaultConf = QString(PLUGIN_DESKTOPS_DIR)+"/../"; QString loaclCong = QString(qgetenv("HOME"))+"/.config/ukui/"; QFile file(loaclCong+"panel.conf"); if(!file.exists()){ copyFileToPath(defaultConf,loaclCong,"panel.conf",false); // QFile::copy(CONFIG_FILE_BACKUP,QString(qgetenv("HOME"))+CONFIG_FILE_LOCAL); } d->mSettings = new UKUi::Settings(QLatin1String("panel"), this); if(!d->mSettings->contains("plugins")){ QFile::remove(QString(qgetenv("HOME"))+CONFIG_FILE_LOCAL); QFile::copy(CONFIG_FILE_BACKUP,QString(qgetenv("HOME"))+CONFIG_FILE_LOCAL); d->mSettings = new UKUi::Settings(QLatin1String("panel"), this); } } else { qDebug()<<"configFile.is not Empty"<mSettings = new UKUi::Settings(configFile, QSettings::IniFormat, this); } const QString panelReset = parser.value(panelResetOption); if(panelReset.isEmpty()){qDebug()<<"ukui-panel --reset";} if(panelReset == "reset"){system("rm $HOME/.config/ukui/panel.conf");} if(panelReset == "replace"){qDebug()<<"ukui-panel --replace";} if(panelReset == "calendar-new"){system("/usr/share/ukui/ukui-panel/ukui-panel-config.sh calendar new && killall ukui-panel");} if(panelReset == "calendar-old"){system("/usr/share/ukui/ukui-panel/ukui-panel-config.sh calendar old && killall ukui-panel");} // This is a workaround for Qt 5 bug #40681. const auto allScreens = screens(); for(QScreen* screen : allScreens) { connect(screen, &QScreen::destroyed, this, &UKUIPanelApplication::screenDestroyed); } connect(this, &QGuiApplication::screenAdded, this, &UKUIPanelApplication::handleScreenAdded); connect(this, &QCoreApplication::aboutToQuit, this, &UKUIPanelApplication::cleanup); QStringList panels = d->mSettings->value("panels").toStringList(); // WARNING: Giving a separate icon theme to the panel is wrong and has side effects. // However, it is optional and can be used as the last resort for avoiding a low // contrast in the case of symbolic SVG icons. (The correct way of doing that is // using a Qt widget style that can assign a separate theme/QPalette to the panel.) mGlobalIconTheme = QIcon::themeName(); const QString iconTheme = d->mSettings->value("iconTheme").toString(); if (!iconTheme.isEmpty()) QIcon::setThemeName(iconTheme); if (panels.isEmpty()) { panels << "panel1"; } #if (QT_VERSION < QT_VERSION_CHECK(5,7,0)) for(int it=0;it= QT_VERSION_CHECK(5,7,0)) for(const QString& i : qAsConst(panels)){ #endif addPanel(i); } } UKUIPanelApplication::~UKUIPanelApplication() { delete d_ptr; } void UKUIPanelApplication::cleanup() { qDeleteAll(mPanels); } void UKUIPanelApplication::addNewPanel() { Q_D(UKUIPanelApplication); QString name("panel_" + QUuid::createUuid().toString()); UKUIPanel *p = addPanel(name); int screenNum = p->screenNum(); IUKUIPanel::Position newPanelPosition = d->computeNewPanelPosition(p, screenNum); p->setPosition(screenNum, newPanelPosition, true); QStringList panels = d->mSettings->value("panels").toStringList(); panels << name; d->mSettings->setValue("panels", panels); // Poupup the configuration dialog to allow user configuration right away // p->showConfigDialog(); } UKUIPanel* UKUIPanelApplication::addPanel(const QString& name) { Q_D(UKUIPanelApplication); UKUIPanel *panel = new UKUIPanel(name, d->mSettings); KWindowEffects::enableBlurBehind(panel->winId(),true); mPanels << panel; // reemit signals connect(panel, &UKUIPanel::deletedByUser, this, &UKUIPanelApplication::removePanel); connect(panel, &UKUIPanel::pluginAdded, this, &UKUIPanelApplication::pluginAdded); connect(panel, &UKUIPanel::pluginRemoved, this, &UKUIPanelApplication::pluginRemoved); return panel; } void UKUIPanelApplication::handleScreenAdded(QScreen* newScreen) { // qDebug() << "UKUIPanelApplication::handleScreenAdded" << newScreen; connect(newScreen, &QScreen::destroyed, this, &UKUIPanelApplication::screenDestroyed); } void UKUIPanelApplication::reloadPanelsAsNeeded() { Q_D(UKUIPanelApplication); // NOTE by PCMan: This is a workaround for Qt 5 bug #40681. // Here we try to re-create the missing panels which are deleted in // UKUIPanelApplication::screenDestroyed(). // qDebug() << "UKUIPanelApplication::reloadPanelsAsNeeded()"; const QStringList names = d->mSettings->value("panels").toStringList(); for(const QString& name : names) { bool found = false; #if (QT_VERSION < QT_VERSION_CHECK(5,7,0)) for(int i=0;i= QT_VERSION_CHECK(5,7,0)) for(UKUIPanel* panel : qAsConst(mPanels)){ #endif if(panel->name() == name) { found = true; break; } } if(!found) { // the panel is found in the config file but does not exist, create it. qDebug() << "Workaround Qt 5 bug #40681: re-create panel:" << name; addPanel(name); } } qApp->setQuitOnLastWindowClosed(true); } void UKUIPanelApplication::screenDestroyed(QObject* screenObj) { // NOTE by PCMan: This is a workaround for Qt 5 bug #40681. // With this very dirty workaround, we can fix ukui/ukui bug #204, #205, and #206. // Qt 5 has two new regression bugs which breaks ukui-panel in a multihead environment. // #40681: Regression bug: QWidget::winId() returns old value and QEvent::WinIdChange event is not emitted sometimes. (multihead setup) // #40791: Regression: QPlatformWindow, QWindow, and QWidget::winId() are out of sync. // Explanations for the workaround: // Internally, Qt mantains a list of QScreens and update it when XRandR configuration changes. // When the user turn off an monitor with xrandr --output --off, this will destroy the QScreen // object which represent the output. If the QScreen being destroyed contains our panel widget, // Qt will call QWindow::setScreen(0) on the internal windowHandle() of our panel widget to move it // to the primary screen. However, moving a window to a different screen is more than just changing // its position. With XRandR, all screens are actually part of the same virtual desktop. However, // this is not the case in other setups, such as Xinerama and moving a window to another screen is // not possible unless you destroy the widget and create it again for a new screen. // Therefore, Qt destroy the widget and re-create it when moving our panel to a new screen. // Unfortunately, destroying the window also destroy the child windows embedded into it, // using XEMBED such as the tray icons. (#206) // Second, when the window is re-created, the winId of the QWidget is changed, but Qt failed to // generate QEvent::WinIdChange event so we have no way to know that. We have to set // some X11 window properties using the native winId() to make it a dock, but this stop working // because we cannot get the correct winId(), so this causes #204 and #205. // // The workaround is very simple. Just completely destroy the panel before Qt has a chance to do // QWindow::setScreen() for it. Later, we reload the panel ourselves. So this can bypassing the Qt bugs. QScreen* screen = static_cast(screenObj); bool reloadNeeded = false; qApp->setQuitOnLastWindowClosed(false); #if (QT_VERSION < QT_VERSION_CHECK(5,7,0)) for(int i=0;i= QT_VERSION_CHECK(5,7,0)) for(UKUIPanel* panel : qAsConst(mPanels)){ #endif QWindow* panelWindow = panel->windowHandle(); if(panelWindow && panelWindow->screen() == screen) { // the screen containing the panel is destroyed // delete and then re-create the panel ourselves QString name = panel->name(); panel->saveSettings(false); delete panel; // delete the panel, so Qt does not have a chance to set a new screen to it. mPanels.removeAll(panel); reloadNeeded = true; qDebug() << "Workaround Qt 5 bug #40681: delete panel:" << name; } } if(reloadNeeded) QTimer::singleShot(1000, this, SLOT(reloadPanelsAsNeeded())); else qApp->setQuitOnLastWindowClosed(true); } void UKUIPanelApplication::removePanel(UKUIPanel* panel) { Q_D(UKUIPanelApplication); Q_ASSERT(mPanels.contains(panel)); mPanels.removeAll(panel); QStringList panels = d->mSettings->value("panels").toStringList(); panels.removeAll(panel->name()); d->mSettings->setValue("panels", panels); panel->deleteLater(); } bool UKUIPanelApplication::isPluginSingletonAndRunnig(QString const & pluginId) const { for (auto const & panel : mPanels) if (panel->isPluginSingletonAndRunnig(pluginId)) return true; return false; } // See UKUIPanelApplication::UKUIPanelApplication for why this isn't good. void UKUIPanelApplication::setIconTheme(const QString &iconTheme) { Q_D(UKUIPanelApplication); d->mSettings->setValue("iconTheme", iconTheme == mGlobalIconTheme ? QString() : iconTheme); QString newTheme = iconTheme.isEmpty() ? mGlobalIconTheme : iconTheme; if (newTheme != QIcon::themeName()) { QIcon::setThemeName(newTheme); #if (QT_VERSION < QT_VERSION_CHECK(5,7,0)) for(int i=0;i= QT_VERSION_CHECK(5,7,0)) for(UKUIPanel* panel : qAsConst(mPanels)){ #endif // panel->update(); // panel->updateConfigDialog(); } } } void UKUIPanelApplication::sigtermHandler(int signo) { qDebug() << "Caught SIGTERM signal, exit with SIGTERM"; exit(signo); } void UKUIPanelApplication::translator(){ m_translator = new QTranslator(this); QString locale = QLocale::system().name(); if (locale == "zh_CN"){ if (m_translator->load(QM_INSTALL)) qApp->installTranslator(m_translator); else qDebug() < * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef UKUIPanelAPPLICATION_H #define UKUIPanelAPPLICATION_H //#include #include "common/ukuiapplication.h" #include "iukuipanelplugin.h" class QScreen; class UKUIPanel; class UKUIPanelApplicationPrivate; /*! * \brief The UKUIPanelApplication class inherits from UKUi::Application and * is therefore the QApplication that we will create and execute in our * main()-function. * * UKUIPanelApplication itself is not a visible panel, rather it is only * the container which holds the visible panels. These visible panels are * UKUIPanel objects which are stored in mPanels. This approach enables us * to have more than one panel (for example one panel at the top and one * panel at the bottom of the screen) without additional effort. */ class UKUIPanelApplication : public UKUi::Application { Q_OBJECT public: /*! * \brief Creates a new UKUIPanelApplication with the given command line * arguments. Performs the following steps: * 1. Initializes the UKUi::Application, sets application name and version. * 2. Handles command line arguments. Currently, the only cmdline argument * is -c = -config = -configfile which chooses a different config file * for the UKUi::Settings. * 3. Creates the UKUi::Settings. * 4. Connects QCoreApplication::aboutToQuit to cleanup(). * 5. Calls addPanel() for each panel found in the config file. If there is * none, adds a new panel. * \param argc * \param argv */ explicit UKUIPanelApplication(int& argc, char** argv); ~UKUIPanelApplication(); void setIconTheme(const QString &iconTheme); /*! * \brief Determines the number of UKUIPanel objects * \return the current number of UKUIPanel objects */ int count() const { return mPanels.count(); } /*! * \brief Checks if a given Plugin is running and has the * IUKUIPanelPlugin::SingleInstance flag set. As Plugins are added to * UKUIPanel instances, this method only iterates over these UKUIPanel * instances and lets them check the conditions. * \param pluginId Plugin Identifier which is the basename of the .desktop * file that specifies the plugin. * \return true if the Plugin is running and has the * IUKUIPanelPlugin::SingleInstance flag set, false otherwise. */ bool isPluginSingletonAndRunnig(QString const & pluginId) const; public slots: /*! * \brief Adds a new UKUIPanel which consists of the following steps: * 1. Create id/name. * 2. Create the UKUIPanel: call addPanel(name). * 3. Update the config file (add the new panel id to the list of panels). * 4. Show the panel configuration dialog so that the user can add plugins. * * This method will create a new UKUIPanel with a new name and add this * to the config file. So this should only be used while the application * is running and the user decides to add a new panel. At application * startup, addPanel() should be used instead. * * \note This slot will be used from the UKUIPanel right-click menu. As we * can only add new panels from a visible panel, we should never run * lxqt-panel without an UKUIPanel. Without a panel, we have just an * invisible application. */ void addNewPanel(); signals: /*! * \brief Signal that re-emits the signal pluginAdded() from UKUIPanel. */ void pluginAdded(); /*! * \brief Signal that re-emits the signal pluginRemoved() from UKUIPanel. */ void pluginRemoved(); private: /*! * \brief Holds all the instances of UKUIPanel. */ QList mPanels; /*! * \brief The global icon theme used by all apps (except for panels perhaps). */ QString mGlobalIconTheme; /*! * \brief Creates a new UKUIPanel with the given name and connects the * appropriate signals and slots. * This method can be used at application startup. * \param name Name of the UKUIPanel as it is used in the config file. * \return The newly created UKUIPanel. */ UKUIPanel* addPanel(const QString &name); /*! * \brief Exit with 15 rather than 0 when killed by SIGTERM signal, * so session manager can restart the panel. * \param caight signal number (15). */ QTranslator *m_translator; static void sigtermHandler(int signo); void translator(); private slots: /*! * \brief Removes the given UKUIPanel which consists of the following * steps: * 1. Remove the panel from mPanels. * 2. Remove the panel from the config file. * 3. Schedule the QObject for deletion: QObject::deleteLater(). * \param panel UKUIPanel instance that should be removed. */ void removePanel(UKUIPanel* panel); /*! * \brief Connects the QScreen::destroyed signal of a new screen to * the screenDestroyed() slot so that we can handle this screens' * destruction as soon as it happens. * \param newScreen The QScreen that was created and added. */ void handleScreenAdded(QScreen* newScreen); /*! * \brief Handles screen destruction. This is a workaround for a Qt bug. * For further information, see the implementation notes. * \param screenObj The QScreen that was destroyed. */ void screenDestroyed(QObject* screenObj); /*! * \brief Reloads the panels. This is the second part of the workaround * mentioned above. */ void reloadPanelsAsNeeded(); /*! * \brief Deletes all UKUIPanel instances that are stored in mPanels. */ void cleanup(); private: /*! * \brief mSettings is the UKUi::Settings object that is used for the * current instance of ukui-panel. Normally, this refers to the config file * $HOME/.config/ukui/panel.conf (on Unix systems). This behaviour can be * changed with the -c command line option. */ UKUIPanelApplicationPrivate *const d_ptr; Q_DECLARE_PRIVATE(UKUIPanelApplication) Q_DISABLE_COPY(UKUIPanelApplication) }; #endif // UKUIPanelAPPLICATION_H ukui-panel-3.0.6.4/panel/ukuipanel.h0000644000175000017500000007140014203402514015616 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2011 Razor team * Authors: * Alexander Sokoloff * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef UKUIPANEL_H #define UKUIPANEL_H #include #include #include #include #include #include #include #include #include "common/ukuisettings.h" #include "iukuipanel.h" #include "ukuipanelglobals.h" #include "highlight-effect.h" class QMenu; class Plugin; class QAbstractItemModel; namespace UKUi { class Settings; class PluginInfo; } class UKUIPanelLayout; class ConfigPanelDialog; class PanelPluginsModel; class WindowNotifier; /*! \brief The UKUIPanel class provides a single ukui-panel. All UKUIPanel * instances should be created and handled by UKUIPanelApplication. In turn, * all Plugins should be created and handled by UKUIPanels. * * UKUIPanel is just the panel, it does not incorporate any functionality. * Each function of the panel is implemented by Plugins, even the mainmenu * (plugin-mainmenu) and the taskbar (plugin-taskbar). So the UKUIPanel is * just the container for several Plugins while the different Plugins * incorporate the functions of the panel. Without the Plugins, the panel * is quite useless because it is just a box occupying space on the screen. * * UKUIPanel itself is a window (QFrame/QWidget) and this class is mainly * responsible for handling the size and position of this window on the * screen(s) as well as the different settings. The handling of the plugins * is outsourced in PanelPluginsModel and UKUIPanelLayout. PanelPluginsModel * is responsible for loading/creating and handling the plugins. * UKUIPanelLayout is inherited from QLayout and set as layout to the * background of UKUIPanel, so UKUIPanelLayout is responsible for the * layout of all the Plugins. * * \sa UKUIPanelApplication, Plugin, PanelPluginsModel, UKUIPanelLayout. */ class UKUI_PANEL_API UKUIPanel : public QFrame, public IUKUIPanel { Q_OBJECT Q_PROPERTY(QString position READ qssPosition) Q_CLASSINFO("D-Bus Interface", "org.ukui.panel.settings") // for configuration dialog friend class ConfigPanelWidget; friend class ConfigPluginsWidget; friend class ConfigPanelDialog; friend class PanelPluginsModel; public: /** * @brief Stores how the panel should be aligned. Obviously, this applies * only if the panel does not occupy 100 % of the available space. If the * panel is vertical, AlignmentLeft means align to the top border of the * screen, AlignmentRight means align to the bottom. */ enum Alignment { AlignmentLeft = -1, //!< Align the panel to the left or top AlignmentCenter = 0, //!< Center the panel AlignmentRight = 1 //!< Align the panel to the right or bottom }; /** * @brief Creates and initializes the UKUIPanel. Performs the following * steps: * 1. Sets Qt window title, flags, attributes. * 2. Creates the panel layout. * 3. Prepares the timers. * 4. Connects signals and slots. * 5. Reads the settings for this panel. * 6. Optionally moves the panel to a valid screen (position-dependent). * 7. Loads the Plugins. * 8. Shows the panel, even if it is hidable (but then, starts the timer). * @param configGroup The name of the panel which is used as identifier * in the config file. * @param settings The settings instance of this ukui panel application. * @param parent Parent QWidget, can be omitted. */ UKUIPanel(const QString &configGroup, UKUi::Settings *settings, QWidget *parent = 0); virtual ~UKUIPanel(); /** * @brief Returns the name of this panel which is also used as identifier * in the config file. */ QString name() { return mConfigGroup; } /** * @brief Reads all the necessary settings from mSettings and stores them * in local variables. Additionally, calls necessary methods like realign() * or updateStyleSheet() which need to get called after changing settings. */ void readSettings(); /** * @brief Creates and shows the popup menu (right click menu). If a plugin * is given as parameter, the menu will be divided in two groups: * plugin-specific options and panel-related options. As these two are * shown together, this menu has to be created by UKUIPanel. * @param plugin The plugin whose menu options will be included in the * context menu. */ void showPopupMenu(Plugin *plugin = 0); // IUKUIPanel overrides ........ IUKUIPanel::Position position() const override { return mPosition; } QRect globalGeometry() const override; /** * @brief calculatePopupWindowPos 计算任务栏弹窗的位置 * @param absolutePos * @param windowSize 窗口尺寸 * @return */ QRect calculatePopupWindowPos(QPoint const & absolutePos, QSize const & windowSize) const override; QRect calculatePopupWindowPos(const IUKUIPanelPlugin *plugin, const QSize &windowSize) const override; void willShowWindow(QWidget * w) override; void pluginFlagsChanged(const IUKUIPanelPlugin * plugin) override; // ........ end of IUKUIPanel overrides /** * @brief Searches for a Plugin in the Plugins-list of this panel. Takes * an IUKUIPanelPlugin as parameter and returns the corresponding Plugin. * @param iPlugin IUKUIPanelPlugin that we are looking for. * @return The corresponding Plugin if it is loaded in this panel, nullptr * otherwise. */ Plugin *findPlugin(const IUKUIPanelPlugin *iPlugin) const; // For QSS properties .................. /** * @brief Returns the position as string * * \sa positionToStr(). */ QString qssPosition() const; /** * @brief Checks if this UKUIPanel can be placed at a given position * on the screen with the given screenNum. The condition for doing so * is that the panel is not located between two screens. * * For example, if position is PositionRight, there should be no screen to * the right of the given screen. That means that there should be no * screen whose left border has a higher x-coordinate than the x-coordinate * of the right border of the given screen. This method iterates over all * screens and checks these conditions. * @param screenNum screen index as it is used by QDesktopWidget methods * @param position position where the panel should be placed * @return true if this panel can be placed at the given position on the * given screen. * * \sa findAvailableScreen(), mScreenNum, mActualScreenNum. */ static bool canPlacedOn(int screenNum, UKUIPanel::Position position); /** * @brief Returns a string representation of the given position. This * string is human-readable and can be used in config files. * @param position position that should be converted to a string. * @return the string representation of the given position, i.e. * "Top", "Left", "Right" or "Bottom". * * \sa strToPosition() */ static QString positionToStr(IUKUIPanel::Position position); /** * @brief Returns an IUKUIPanel::Position from the given string. This can * be used to retrieve IUKUIPanel::Position values from the config files. * @param str string that should be converted to IUKUIPanel::Position * @param defaultValue value that will be returned if the string can not * be converted to an IUKUIPanel::Position. * @return IUKUIPanel::Position that was determined from str or * defaultValue if str could not be converted. * * \sa positionToStr() */ static IUKUIPanel::Position strToPosition(const QString &str, IUKUIPanel::Position defaultValue); static IUKUIPanel::Position intToPosition(const int p, IUKUIPanel::Position defaultValue); // Settings int iconSize() const override { return mIconSize; } //!< Implement IUKUIPanel::iconSize(). int lineCount() const override { return mLineCount; } //!< Implement IUKUIPanel::lineCount(). int panelSize() const override{ return mPanelSize; } int length() const { return mLength; } bool lengthInPercents() const { return mLengthInPercents; } UKUIPanel::Alignment alignment() const { return mAlignment; } int screenNum() const { return mScreenNum; } QColor fontColor() const { return mFontColor; } QColor backgroundColor() const { return mBackgroundColor; } QString backgroundImage() const { return mBackgroundImage; } int opacity() const { return mOpacity; } int reserveSpace() const { return mReserveSpace; } bool hidable() const { return mHidable; } bool visibleMargin() const { return mVisibleMargin; } int animationTime() const { return mAnimationTime; } int showDelay() const { return mShowDelayTimer.interval(); } QString iconTheme() const; /*! * \brief Checks if a given Plugin is running and has the * IUKUIPanelPlugin::SingleInstance flag set. * \param pluginId Plugin Identifier which is the basename of the * .desktop file that specifies the plugin. * \return true if the Plugin is running and has the * IUKUIPanelPlugin::SingleInstance flag set, false otherwise. */ bool isPluginSingletonAndRunnig(QString const & pluginId) const; /*! * \brief Updates the config dialog. Used for updating its icons * when the panel-specific icon theme changes. */ // void updateConfigDialog() const; public slots: /** * @brief Shows the QWidget and makes it visible on all desktops. This * method is NOT related to showPanel(), hidePanel() and hidePanelWork() * which handle the UKUi hiding by resizing the panel. */ void show(); /** * @brief Shows the panel (immediately) after it had been hidden before. * Stops the QTimer mHideTimer. This it NOT the same as QWidget::show() * because hiding the panel in UKUi is done by making it very thin. So * this method in fact restores the original size of the panel. * \param animate flag for the panel show-up animation disabling (\sa mAnimationTime). * * \sa mHidable, mHidden, mHideTimer, hidePanel(), hidePanelWork() */ void showPanel(bool animate); /** * @brief Hides the panel (delayed) by starting the QTimer mHideTimer. * When this timer times out, hidePanelWork() will be called. So this * method is called when the cursor leaves the panel area but the panel * will be hidden later. * * \sa mHidable, mHidden, mHideTimer, showPanel(), hidePanelWork() */ void hidePanel(); /** * @brief Actually hides the panel. Will be invoked when the QTimer * mHideTimer times out. That timer will be started by showPanel(). This * is NOT the same as QWidget::hide() because hiding the panel in UKUi is * done by making the panel very thin. So this method in fact makes the * panel very thin while the QWidget stays visible. * * \sa mHidable, mHidden, mHideTimer, showPanel(), hidePanel() */ void hidePanelWork(); // Settings /** * @brief All the setter methods are designed similar: * 1. Check if the given value is different from the current value. If not, * do not do anything and return. * 2. Set the value. * 3. If parameter save is true, call saveSettings(true) to store the * new settings on the disk. * 4. If necessary, propagate the new value to child objects, e.g. to * mLayout. * 5. If necessary, call update methods like realign() or * updateStyleSheet(). * @param value The value that should be set. * @param save If true, saveSettings(true) will be called. */ void setPanelSize(int value, bool save); void setIconSize(int value, bool save); //!< \sa setPanelSize() void setLineCount(int value, bool save); //!< \sa setPanelSize() void setLength(int length, bool inPercents, bool save); //!< \sa setPanelSize() void setPosition(int screen, IUKUIPanel::Position position, bool save); //!< \sa setPanelSize() void setAlignment(UKUIPanel::Alignment value, bool save); //!< \sa setPanelSize() void setFontColor(QColor color, bool save); //!< \sa setPanelSize() void setBackgroundColor(QColor color, bool save); //!< \sa setPanelSize() void setReserveSpace(bool reserveSpace, bool save); //!< \sa setPanelSize() void setHidable(bool hidable, bool save); //!< \sa setPanelSize() void setVisibleMargin(bool visibleMargin, bool save); //!< \sa setPanelSize() void setAnimationTime(int animationTime, bool save); //!< \sa setPanelSize() void setShowDelay(int showDelay, bool save); //!< \sa setPanelSize() void setIconTheme(const QString& iconTheme); /** * @brief Saves the current configuration, i.e. writes the current * configuration varibles to mSettings. * @param later Determines if the settings are written immediately or * after a short delay. If later==true, the QTimer mDelaySave is started. * As soon as this timer times out, saveSettings(false) will be called. If * later==false, settings will be written. */ void saveSettings(bool later=false); /** * @brief Checks if the panel can be placed on the current screen at the * current position. If it can not, it will be moved on another screen * where the desired position is possible. */ void ensureVisible(); signals: /** * @brief This signal gets emitted whenever this panel receives a * QEvent::LayoutRequest, i.e. "Widget layout needs to be redone.". * The PanelPluginsModel will connect this signal to the individual * plugins so they can realign, too. */ void realigned(); /** * @brief This signal gets emitted at the end of * userRequestForDeletion() which in turn gets called when the user * decides to remove a panel. This signal is used by * UKUIPanelApplication to get notified whenever an UKUIPanel should * be removed. * @param self This UKUIPanel. UKUIPanelApplication will use this * parameter to identify the UKUIPanel that should be removed. */ void deletedByUser(UKUIPanel *self); /** * @brief This signal is just a relay signal. The pluginAdded signal * of the PanelPluginsModel (mPlugins) will be connected to this * signal. Thereby, we can make this signal of a private member * available as a public signal. * Currently, this signal is used by UKUIPanelApplication which * will further re-emit this signal. */ void pluginAdded(); /** * @brief This signal is just a relay signal. The pluginRemoved signal * of the PanelPluginsModel (mPlugins) will be connected to this * signal. Thereby, we can make this signal of a private member * available as a public signal. * Currently, this signal is used by UKUIPanelApplication which * will further re-emit this signal. */ void pluginRemoved(); protected: /** * @brief Overrides QObject::event(QEvent * e). Some functions of * the panel will be triggered by these events, e.g. showing/hiding * the panel or showing the context menu. * @param event The event that was received. * @return "QObject::event(QEvent *e) should return true if the event e * was recognized and processed." This is done by passing the event to * QFrame::event(QEvent *e) at the end. */ bool event(QEvent *event) override; /** * @brief Overrides QWidget::showEvent(QShowEvent * event). This * method is called when a widget (in this case: the UKUIPanel) is * shown. The call could happen before and after the widget is shown. * This method is just overridden to get notified when the UKUIPanel * will be shown. Then, UKUIPanel will call realign(). * @param event The QShowEvent sent by Qt. */ void showEvent(QShowEvent *event) override; void paintEvent(QPaintEvent *); void mouseMoveEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent* event); void mousePressEvent(QMouseEvent *event); void enterEvent(QEvent *event); void leaveEvent(QEvent *event); public slots: /** * @brief Shows the ConfigPanelDialog and shows the "Config Panel" * page, i.e. calls showConfigPanelPage(). If the dialog does not * exist yet, it will be created before. * * The "Configure Panel" button in the context menu of the panel will * be connected to this slot so this method gets called whenever the * user clicks that button. * * Furthermore, this method will be called by UKUIPanelApplication * when a new plugin gets added (the UKUIPanel instances are handled * by UKUIPanelApplication). That is why this method/slot has to be * public. */ // void showConfigDialog(); private slots: /** * @brief Shows the ConfigPanelDialog and shows the "Config Plugins" * page, i.e. calls showConfigPluginsPage(). If the dialog does not * exist yet, it will be created before. * * The "Manage Widgets" button in the context menu of the panel will * be connected to this slot so this method gets called whenever the * user clicks that button. */ // void showAddPluginDialog(); /** * @brief Recalculates the geometry of the panel and reserves the * window manager strut, i.e. it calls setPanelGeometry() and * updateWmStrut(). * Two signals will be connected to this slot: * 1. QDesktopWidget::workAreaResized(int screen) which will be emitted * when the work area available (on screen) changes. * 2. UKUi::Application::themeChanged(), i.e. when the user changes * the theme. */ void systeMonitor(); void showDesktop(); void showTaskView(); void showNightModeButton(); void adjustPanel(); void realign(); /** * @brief Moves a plugin in PanelPluginsModel, i.e. calls * PanelPluginsModel::movePlugin(Plugin * plugin, QString const & nameAfter). * UKUIPanelLayout::pluginMoved() will be connected to this slot so * it gets called whenever a plugin was moved in the layout by the user. * @param plug */ void pluginMoved(Plugin * plug); /** * @brief Removes this panel's entries from the config file and emits * the deletedByUser signal. * The "Remove Panel" button in the panel's contex menu will * be connected to this slot, so this method will be called whenever * the user clicks "Remove Panel". */ void userRequestForDeletion(); private: int scale; /** * @brief The UKUIPanelLayout of this panel. All the Plugins will be added * to the UI via this layout. */ UKUIPanelLayout* mLayout; /** * @brief The UKUi::Settings instance as retrieved from * UKUIPanelApplication. */ UKUi::Settings *mSettings; /** * @brief The background widget for the panel. This background widget will * have the background color or the background image if any of these is * set. This background widget will have the UKUIPanelLayout mLayout which * will in turn contain all the Plugins. */ QFrame *UKUIPanelWidget; /** * @brief The name of the panel which will also be used as an identifier * for config files. */ QString mConfigGroup; /** * @brief Pointer to the PanelPluginsModel which will store all the Plugins * that are loaded. */ QScopedPointer mPlugins; /** * @brief object for storing info if some standalone window is shown * (for preventing hide) */ QScopedPointer mStandaloneWindows; /** * @brief Returns the screen index of a screen on which this panel could * be placed at the given position. If possible, the current screen index * is preserved. So, if the panel can be placed on the current screen, the * index of that screen will be returned. * @param position position at which the panel should be placed. * @return The current screen index if the panel can be placed on the * current screen or the screen index of a screen that it can be placed on. * * \sa canPlacedOn(), mScreenNum, mActualScreenNum. */ int findAvailableScreen(UKUIPanel::Position position); /** * @brief Update the window manager struts _NET_WM_PARTIAL_STRUT and * _NET_WM_STRUT for this widget. "The purpose of struts is to reserve * space at the borders of the desktop. This is very useful for a * docking area, a taskbar or a panel, for instance. The Window Manager * should take this reserved area into account when constraining window * positions - maximized windows, for example, should not cover that * area." * \sa http://standards.freedesktop.org/wm-spec/wm-spec-latest.html#NETWMSTRUT */ void updateWmStrut(); /** * @brief Loads the plugins, i.e. creates a new PanelPluginsModel. * Connects the signals and slots and adds all the plugins to the * layout. */ void loadPlugins(); void reloadPlugins(QString model); QStringList readConfig(QString model); void checkPlugins(QStringList list); void movePlugins(QStringList list); /** * @brief Calculates and sets the geometry (i.e. the position and the size * on the screen) of the panel. Considers alignment, position, if the panel * is hidden and if its geometry should be set with animation. * \param animate flag if showing/hiding the panel should be animated. */ void setPanelGeometry(bool animate = false); /** * @brief Sets the contents margins of the panel according to its position * and hiddenness. All margins are zero for visible panels. */ void setMargins(); /** * @brief Calculates the height of the panel if it is horizontal or the * width if the panel is vertical. Considers if the panel is hidden and * ensures that the result is at least PANEL_MINIMUM_SIZE. * @return The height/width of the panel. */ int getReserveDimension(); /** * @brief Stores the size of the panel, i.e. the height of a horizontal * panel or the width of a vertical panel in pixels. If the panel is * hidden (which is achieved by making the panel very thin), this value * is unchanged. So this value stores the size of the non-hidden panel. * * \sa panelSize(), setPanelSize(). */ void styleAdjust(); int mPanelSize; /** * @brief Stores the edge length of the panel icons in pixels. * * \sa IUKUIPanel::iconSize(), setIconSize(). */ int mIconSize; /** * @brief Stores the number of lines/rows of the panel. * * \sa IUKUIPanel::lineCount(), setLineCount(). */ int mLineCount; /** * @brief Stores the length of the panel, i.e. the width of a horizontal * panel or the height of a vertical panel. The unit of this value is * determined by mLengthInPercents. * * \sa mLengthInPercents */ int mLength; /** * @brief Stores if mLength is stored in pixels or relative to the * screen size in percents. If true, the length is stored in percents, * otherwise in pixels. * * \sa mLength */ bool mLengthInPercents; /** * @brief Stores how this panel is aligned. The meaning of this value * differs for horizontal and vertical panels. * * \sa Alignment. */ Alignment mAlignment; /** * @brief Stores the position where the panel is shown */ IUKUIPanel::Position mPosition; /** * @brief Returns the index of the screen on which this panel should be * shown. This is the user configured value which can differ from the * screen that the panel is actually shown on. If the panel can not be * shown on the configured screen, UKUIPanel will determine another * screen. The screen that the panel is actually shown on is stored in * mActualScreenNum. * * @return The index of the screen on which this panel should be shown. * * \sa mActualScreenNum, canPlacedOn(), findAvailableScreen(). */ int mScreenNum; /** * @brief screen that the panel is currently shown at (this could * differ from mScreenNum). * * \sa mScreenNum, canPlacedOn(), findAvailableScreen(). */ int mActualScreenNum; /** * @brief QTimer for delayed saving of changed settings. In many cases, * instead of storing changes to disk immediately we start this timer. * If this timer times out, we store the changes to disk. This has the * advantage that we can store a couple of changes with only one write to * disk. * * \sa saveSettings() */ QTimer mDelaySave; /** * @brief Stores if the panel is hidable, i.e. if the panel will be * hidden after the cursor has left the panel area. * * \sa mVisibleMargin, mHidden, mHideTimer, showPanel(), hidePanel(), hidePanelWork() */ bool mHidable; /** * @brief Stores if the hidable panel should have a visible margin. * * \sa mHidable, mHidden, mHideTimer, showPanel(), hidePanel(), hidePanelWork() */ bool mVisibleMargin; /** * @brief Stores if the panel is currently hidden. * * \sa mHidable, mVisibleMargin, mHideTimer, showPanel(), hidePanel(), hidePanelWork() */ bool mHidden; /** * @brief QTimer for hiding the panel. When the cursor leaves the panel * area, this timer will be started. After this timer has timed out, the * panel will actually be hidden. * * \sa mHidable, mVisibleMargin, mHidden, showPanel(), hidePanel(), hidePanelWork() */ QTimer mHideTimer; /** * @brief Stores the duration of auto-hide animation. * * \sa mHidden, mHideTimer, showPanel(), hidePanel(), hidePanelWork() */ int mAnimationTime; /** * @brief The timer used for showing an auto-hiding panel wih delay. * * \sa showPanel() */ QTimer mShowDelayTimer; QColor mFontColor; //!< Font color that is used in the style sheet. QColor mBackgroundColor; //!< Background color that is used in the style sheet. QString mBackgroundImage; //!< Background image that is used in the style sheet. /** * @brief Determines the opacity of the background color. The value * should be in the range from 0 to 100. This will not affect the opacity * of a background image. */ int mOpacity; /*! * \brief Flag if the panel should reserve the space under it as not usable * for "normal" windows. Usable for not 100% wide/hight or hiddable panels, * if user wants maximized windows go under the panel. * * \sa updateWmStrut() */ bool mReserveSpace; /** * @brief Pointer to the current ConfigPanelDialog if there is any. Make * sure to test this pointer for validity because it is lazily loaded. */ // QPointer mConfigDialog; //ConfigPanelDialog *mConfigDialog; //QPointer mConfigWidget; /** * @brief The animation used for showing/hiding an auto-hiding panel. */ QPropertyAnimation *mAnimation; /** * @brief Flag for providing the configuration options in panel's context menu */ bool mLockPanel; double transparency; // settings should be kept private for security UKUi::Settings *settings() const { return mSettings; } QDBusInterface *m_cloudInterface; IUKUIPanel::Position oldpos; QMenu * menu; QAction * m_lockAction; /** * @brief mDbusXrandInter * 华为990双屏的dbus */ QDBusInterface *mDbusXrandInter; QRect mcurrentScreenRect; QString flag_hw990; IUKUIPanel::Position areaDivid(QPoint globalpos); int movelock = -1; void connectToServer(); private slots: void panelReset(); void keyChangedSlot(const QString &key); void priScreenChanged(int x, int y, int width, int height); public: QGSettings *gsettings; QGSettings *transparency_gsettings; QGSettings *scale_gsetting; int scale_flag; QTimer *time; }; #endif // UKUIPANEL_H ukui-panel-3.0.6.4/CMakeLists.txt0000644000175000017500000001560114203402514015112 0ustar fengfengcmake_minimum_required(VERSION 3.1.0 FATAL_ERROR) project(ukui-panel) option(WITH_SCREENSAVER_FALLBACK "Include support for converting the deprecated 'screensaver' plugin to 'quicklaunch'. This requires the ukui-leave (ukui-session) to be installed in runtime." OFF) #判断编译器类型,如果是gcc编译器,则在编译选项中加入c++11支持 if(CMAKE_COMPILER_IS_GNUCXX) set(CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}") message(STATUS "optional:-std=c++11") endif(CMAKE_COMPILER_IS_GNUCXX) # additional cmake files set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake) macro(setByDefault VAR_NAME VAR_VALUE) if(NOT DEFINED ${VAR_NAME}) set (${VAR_NAME} ${VAR_VALUE}) endif(NOT DEFINED ${VAR_NAME}) endmacro() include(GNUInstallDirs) setByDefault(CUSTOM_QT_5_6_VERSION Yes) setByDefault(CUSTOM_QT_5_12_VERSION No) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_POSITION_INDEPENDENT_CODE ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOUIC ON) set(CMAKE_AUTORCC ON) set(REQUIRED_QT_VERSION "5.6.1") set(KF5_MINIMUM_VERSION "5.18.0") set(QT_MINIMUM_VERSION "5.6.1") set(UKUI_MINIMUM_VERSION "0.14.1") set(QTXDG_MINIMUM_VERSION "3.3.1") find_package(Qt5DBus ${REQUIRED_QT_VERSION} REQUIRED) find_package(Qt5LinguistTools ${REQUIRED_QT_VERSION} REQUIRED) find_package(Qt5Widgets ${REQUIRED_QT_VERSION} REQUIRED) find_package(Qt5X11Extras ${REQUIRED_QT_VERSION} REQUIRED) find_package(Qt5Xml ${REQUIRED_QT_VERSION} REQUIRED) find_package(KF5WindowSystem ${KF5_MINIMUM_VERSION} REQUIRED) find_package(Qt5 ${QT_MINIMUM_VERSION} CONFIG REQUIRED Widgets DBus X11Extras LinguistTools) find_package(Qt5Xdg ${QTXDG_MINIMUM_VERSION} REQUIRED) find_package(X11 REQUIRED) find_package(Qt5LinguistTools) find_package(PkgConfig) pkg_check_modules(Gsetting REQUIRED gsettings-qt) include_directories(${Gsetting_INCLUDE_DIRS}) set(LIBRARIES ${Gsetting_LIBRARIES} -lukui-log4qt ) # Patch Version set(UKUI_VERSION 3.0) set(UKUI_PANEL_PATCH_VERSION 0) set(UKUI_MAJOR_VERSION 3) set(UKUI_MINOR_VERSION 0) #set(UKUI_TRANSLATIONS_DIR "${CMAKE_INSTALL_FULL_DATAROOTDIR}/ukui/translations/") set(UKUI_PANEL_VERSION ${UKUI_MAJOR_VERSION}.${UKUI_MINOR_VERSION}.${UKUI_PANEL_PATCH_VERSION}) add_definitions("-DUKUI_PANEL_VERSION=\"${UKUI_PANEL_VERSION}\"") include(./cmake/ukui-build-tools/modules/UKUiPreventInSourceBuilds.cmake) #include(./cmake/ukui-build-tools/modules/UKUiTranslate.cmake) # All UKUiCompilerSettings except CMAKE_MODULE_LINKER_FLAGS work just fine # So we reset only these Flags after loading UKUiCompilerSettings # ukui-build-tools: # set(CMAKE_MODULE_LINKER_FLAGS "-Wl,--no-undefined ${SYMBOLIC_FLAGS} ${CMAKE_MODULE_LINKER_FLAGS}") message(STATUS "==OLD== CMAKE_MODULE_LINKER_FLAGS: ${CMAKE_MODULE_LINKER_FLAGS}") set( OLD_CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS}") set(CMAKE_MODULE_LINKER_FLAGS "${OLD_CMAKE_MODULE_LINKER_FLAGS} ${SYMBOLIC_FLAGS}") # Warning: This must be before add_subdirectory(panel). Move with caution. set(PLUGIN_DIR "${CMAKE_INSTALL_FULL_LIBDIR}/ukui-panel") add_definitions( -DPLUGIN_DIR=\"${PLUGIN_DIR}\" ) #Add PACKAGE_DATA_DIR set(PACKAGE_DATA_DIR "/usr/share/ukui-panel") add_definitions( -DPACKAGE_DATA_DIR=\"${PACKAGE_DATA_DIR}\" -DQT_MESSAGELOGCONTEXT ) message(STATUS "CMAKE Module linker flags: ${CMAKE_MODULE_LINKER_FLAGS}") message(STATUS "Panel plugins location: ${PLUGIN_DIR}") ######################################################################### # Plugin system # You can enable/disable building of the plugin using cmake options. # cmake -DWORLDCLOCK_PLUGIN=Yes .. # Enable worldclock plugin # cmake -DWORLDCLOCK_PLUGIN=No .. # Disable worldclock plugin include("cmake/BuildPlugin.cmake") include(./cmake/ukui-build-tools/modules/UKUiTranslateDesktop.cmake) include(./cmake/ukui-build-tools/modules/UKUiTranslationLoader.cmake) set(ENABLED_PLUGINS) # list of enabled plugins set(STATIC_PLUGINS) # list of statically linked plugins setByDefault(QUICKLAUNCH_PLUGIN No) if(QUICKLAUNCH_PLUGIN) list(APPEND STATIC_PLUGINS "quicklaunch") add_definitions(-DWITH_QUICKLAUNCH_PLUGIN) list(APPEND ENABLED_PLUGINS "Quicklaunch") add_subdirectory(plugin-quicklaunch) endif() setByDefault(SHOWDESKTOP_PLUGIN Yes) if(SHOWDESKTOP_PLUGIN) list(APPEND STATIC_PLUGINS "showdesktop") add_definitions(-DWITH_SHOWDESKTOP_PLUGIN) list(APPEND ENABLED_PLUGINS "Show Desktop") add_subdirectory(plugin-showdesktop) endif() setByDefault(TASKBAR_PLUGIN Yes) if(TASKBAR_PLUGIN) list(APPEND STATIC_PLUGINS "taskbar") add_definitions(-DWITH_TASKBAR_PLUGIN) list(APPEND ENABLED_PLUGINS "Taskbar") add_subdirectory(plugin-taskbar) endif() add_subdirectory(ukui-flash-disk) #add_subdirectory(ukui-calendar) add_subdirectory(panel-daemon) add_subdirectory(sni-daemon) add_subdirectory(sni-xembed-proxy) setByDefault(STATUSNOTIFIER_PLUGIN Yes) if(STATUSNOTIFIER_PLUGIN) list(APPEND STATIC_PLUGINS "statusnotifier") add_definitions(-DWITH_STATUSNOTIFIER_PLUGIN) list(APPEND ENABLED_PLUGINS "Status Notifier") add_subdirectory(plugin-statusnotifier) endif() setByDefault(SPACER_PLUGIN Yes) if(SPACER_PLUGIN) list(APPEND STATIC_PLUGINS "spacer") add_definitions(-DWITH_SPACER_PLUGIN) list(APPEND ENABLED_PLUGINS "Spacer") add_subdirectory(plugin-spacer) endif() setByDefault(CALENDAR_PLUGIN Yes) if(CALENDAR_PLUGIN) list(APPEND ENABLED_PLUGINS "calendar") add_subdirectory(plugin-calendar) endif(CALENDAR_PLUGIN) setByDefault(NIGHTMODE_PLUGIN Yes) if(NIGHTMODE_PLUGIN) list(APPEND ENABLED_PLUGINS "nightmode") add_subdirectory(plugin-nightmode) endif(NIGHTMODE_PLUGIN) setByDefault(STARTBAR_PLUGIN Yes) if(STARTBAR_PLUGIN) list(APPEND ENABLED_PLUGINS "startbar") add_subdirectory(plugin-startbar) endif(STARTBAR_PLUGIN) ######################################################################### message(STATUS "**************** The following plugins will be built ****************") foreach (PLUGIN_STR ${ENABLED_PLUGINS}) message(STATUS " ${PLUGIN_STR}") endforeach() message(STATUS "*********************************************************************") add_subdirectory(panel) file(GLOB_RECURSE QRC_SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.qrc) ## translation #set(UKUI_TRANSLATIONS_DIR ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DATAROOTDIR}/ukui/) #add_definitions( # -DUKUI_TRANSLATIONS_DIR="${UKUI_TRANSLATIONS_DIR}" #) #if (NOT DEFINED UPDATE_TRANSLATIONS) # set(UPDATE_TRANSLATIONS "No") #endif() ## To create a new ts file: lupdate -recursive . -target-language zh_CN -ts panel/resources/ukui-panel_zh_CN.ts #file(GLOB TS_FILES "${CMAKE_CURRENT_SOURCE_DIR}/panel/resources/*.ts") ## cmake -DUPDATE_TRANSLATIONS=yes #if (UPDATE_TRANSLATIONS) # qt5_create_translation(QM_FILES ${CMAKE_SOURCE_DIR} ${TS_FILES}) #else() # qt5_add_translation(QM_FILES ${TS_FILES}) #endif() #add_custom_target(translations ALL DEPENDS ${QM_FILES}) #install(FILES ${QM_FILES} DESTINATION ${UKUI_TRANSLATIONS_DIR}) ukui-panel-3.0.6.4/plugin-spacer/0000755000175000017500000000000014203402514015120 5ustar fengfengukui-panel-3.0.6.4/plugin-spacer/spacerconfiguration.ui0000644000175000017500000000523214203402514021526 0ustar fengfeng SpacerConfiguration 0 0 289 135 Spacer Settings Space width: 4 2048 8 Space type: Qt::Horizontal QDialogButtonBox::Close fixed false expandable buttons clicked(QAbstractButton*) SpacerConfiguration close() 20 20 20 20 sizeFixedRB toggled(bool) sizeSB setEnabled(bool) 152 21 244 21 ukui-panel-3.0.6.4/plugin-spacer/spacerconfiguration.cpp0000644000175000017500000000640714203402514021700 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2015 LXQt team * Authors: * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "spacerconfiguration.h" #include "ui_spacerconfiguration.h" //Note: strings can't actually be translated here (in static initialization time) // the QT_TR_NOOP here is just for qt translate tools to get the strings for translation const QStringList SpacerConfiguration::msTypes = { QStringLiteral(QT_TR_NOOP("lined")) , QStringLiteral(QT_TR_NOOP("dotted")) , QStringLiteral(QT_TR_NOOP("invisible")) }; SpacerConfiguration::SpacerConfiguration(PluginSettings *settings, QWidget *parent) : UKUIPanelPluginConfigDialog(settings, parent), ui(new Ui::SpacerConfiguration) { setAttribute(Qt::WA_DeleteOnClose); setObjectName(QStringLiteral("SpacerConfigurationWindow")); ui->setupUi(this); //Note: translation is needed here in runtime (translator is attached already) for (auto const & type : msTypes) ui->typeCB->addItem(tr(type.toStdString().c_str()), type); loadSettings(); connect(ui->sizeSB, static_cast(&QSpinBox::valueChanged), this, &SpacerConfiguration::sizeChanged); connect(ui->typeCB, static_cast(&QComboBox::currentIndexChanged), this, &SpacerConfiguration::typeChanged); //Note: if there will be more than 2 radio buttons for width/size type, this simple setting logic will break connect(ui->sizeExpandRB, &QAbstractButton::toggled, this, &SpacerConfiguration::widthTypeChanged); } SpacerConfiguration::~SpacerConfiguration() { delete ui; } void SpacerConfiguration::loadSettings() { ui->sizeSB->setValue(settings().value(QStringLiteral("size"), 8).toInt()); ui->typeCB->setCurrentIndex(ui->typeCB->findData(settings().value(QStringLiteral("spaceType"), msTypes[0]).toString())); const bool expandable = settings().value(QStringLiteral("expandable"), false).toBool(); ui->sizeExpandRB->setChecked(expandable); ui->sizeFixedRB->setChecked(!expandable); ui->sizeSB->setDisabled(expandable); } void SpacerConfiguration::sizeChanged(int value) { settings().setValue(QStringLiteral("size"), value); } void SpacerConfiguration::typeChanged(int index) { settings().setValue(QStringLiteral("spaceType"), ui->typeCB->itemData(index, Qt::UserRole)); } void SpacerConfiguration::widthTypeChanged(bool expandableChecked) { settings().setValue(QStringLiteral("expandable"), expandableChecked); } ukui-panel-3.0.6.4/plugin-spacer/spacerconfiguration.h0000644000175000017500000000326014203402514021337 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2015 LXQt team * Authors: * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef SPACERCONFIGURATION_H #define SPACERCONFIGURATION_H #include "../panel/ukuipanelpluginconfigdialog.h" #include "../panel/pluginsettings.h" class QAbstractButton; namespace Ui { class SpacerConfiguration; } class SpacerConfiguration : public UKUIPanelPluginConfigDialog { Q_OBJECT public: explicit SpacerConfiguration(PluginSettings *settings, QWidget *parent = nullptr); ~SpacerConfiguration(); public: static const QStringList msTypes; private: Ui::SpacerConfiguration *ui; private slots: /* Saves settings in conf file. */ void loadSettings(); void sizeChanged(int value); void typeChanged(int index); void widthTypeChanged(bool expandableChecked); }; #endif // SPACERCONFIGURATION_H ukui-panel-3.0.6.4/plugin-spacer/spacer.h0000644000175000017500000000501514203402514016547 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2015 LXQt team * Authors: * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef SPACER_H #define SPACER_H #include "../panel/iukuipanelplugin.h" #include class SpacerWidget : public QFrame { Q_OBJECT Q_PROPERTY(QString type READ getType) Q_PROPERTY(QString orientation READ getOrientation) public: const QString& getType() const throw () { return mType; } void setType(QString const & type); const QString& getOrientation() const throw () { return mOrientation; } void setOrientation(QString const & orientation); private: QString mType; QString mOrientation; }; class Spacer : public QObject, public IUKUIPanelPlugin { Q_OBJECT public: Spacer(const IUKUIPanelPluginStartupInfo &startupInfo); virtual QWidget *widget() override { return &mSpacer; } virtual QString themeId() const override { return QStringLiteral("Spacer"); } bool isSeparate() const override { return true; } bool isExpandable() const override { return mExpandable; } virtual IUKUIPanelPlugin::Flags flags() const override { return HaveConfigDialog; } QDialog *configureDialog() override; virtual void realign() override; private slots: virtual void settingsChanged() override; private: void setSizes(); private: SpacerWidget mSpacer; int mSize; bool mExpandable; }; class SpacerPluginLibrary: public QObject, public IUKUIPanelPluginLibrary { Q_OBJECT // Q_PLUGIN_METADATA(IID "lxqt.org/Panel/PluginInterface/3.0") Q_INTERFACES(IUKUIPanelPluginLibrary) public: IUKUIPanelPlugin *instance(const IUKUIPanelPluginStartupInfo &startupInfo) const { return new Spacer(startupInfo);} }; #endif ukui-panel-3.0.6.4/plugin-spacer/spacer.cpp0000644000175000017500000000724314203402514017107 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2015 LXQt team * Authors: * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "spacer.h" #include "spacerconfiguration.h" #include void SpacerWidget::setType(QString const & type) { if (type != mType) { mType = type; QEvent e{QEvent::ThemeChange}; QApplication::sendEvent(this, &e); } } void SpacerWidget::setOrientation(QString const & orientation) { if (orientation != mOrientation) { mOrientation = orientation; QEvent e{QEvent::ThemeChange}; QApplication::sendEvent(this, &e); } } /************************************************ ************************************************/ Spacer::Spacer(const IUKUIPanelPluginStartupInfo &startupInfo) : QObject() , IUKUIPanelPlugin(startupInfo) , mSize(8) , mExpandable(false) { settingsChanged(); } /************************************************ ************************************************/ void Spacer::settingsChanged() { mSize = settings()->value(QStringLiteral("size"), 8).toInt(); const bool old_expandable = mExpandable; mExpandable = settings()->value(QStringLiteral("expandable"), false).toBool(); mSpacer.setType(settings()->value(QStringLiteral("spaceType"), SpacerConfiguration::msTypes[0]).toString()); setSizes(); if (old_expandable != mExpandable) pluginFlagsChanged(); } /************************************************ ************************************************/ QDialog *Spacer::configureDialog() { return new SpacerConfiguration(settings()); } /************************************************ ************************************************/ void Spacer::setSizes() { if (mExpandable) { mSpacer.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); mSpacer.setMinimumSize({1, 1}); mSpacer.setMaximumSize({QWIDGETSIZE_MAX, QWIDGETSIZE_MAX}); mSpacer.setOrientation(panel()->isHorizontal() ? QStringLiteral("horizontal") : QStringLiteral("vertical")); } else { if (panel()->isHorizontal()) { mSpacer.setOrientation(QStringLiteral("horizontal")); mSpacer.setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding); mSpacer.setFixedWidth(mSize); mSpacer.setMinimumHeight(0); mSpacer.setMaximumHeight(QWIDGETSIZE_MAX); } else { mSpacer.setOrientation(QStringLiteral("vertical")); mSpacer.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); mSpacer.setFixedHeight(mSize); mSpacer.setMinimumWidth(0); mSpacer.setMaximumWidth(QWIDGETSIZE_MAX); } } } /************************************************ ************************************************/ void Spacer::realign() { setSizes(); } ukui-panel-3.0.6.4/plugin-spacer/resources/0000755000175000017500000000000014203402514017132 5ustar fengfengukui-panel-3.0.6.4/plugin-spacer/resources/spacer.desktop.in0000644000175000017500000000023214203402514022404 0ustar fengfeng[Desktop Entry] Type=Service ServiceTypes=UKUIPanel/Plugin Name=Spacer Comment=Space between widgets Icon=bookmark-new #TRANSLATIONS_DIR=../translations ukui-panel-3.0.6.4/plugin-spacer/CMakeLists.txt0000644000175000017500000000031114203402514017653 0ustar fengfengset(PLUGIN "spacer") set(HEADERS spacer.h spacerconfiguration.h ) set(SOURCES spacer.cpp spacerconfiguration.cpp ) set(UIS spacerconfiguration.ui ) BUILD_UKUI_PLUGIN(${PLUGIN}) ukui-panel-3.0.6.4/plugin-taskbar/0000755000175000017500000000000014204636776015316 5ustar fengfengukui-panel-3.0.6.4/plugin-taskbar/ukuitaskbutton.h0000644000175000017500000001534114203402514020543 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2011 Razor team * 2014 LXQt team * Authors: * Alexander Sokoloff * Kuzma Shapran * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef UKUITASKBUTTON_H #define UKUITASKBUTTON_H #include #include #include #include #include "../panel/iukuipanel.h" //#include #include #include "../panel/ukuicontrolstyle.h" #include "quicklaunchaction.h" #include #include "../panel/customstyle.h" #include #include #include class QPainter; class QPalette; class QMimeData; class UKUITaskGroup; class UKUITaskBar; class IUKUIPanelPlugin; class QuicklaunchMenu:public QMenu { public: QuicklaunchMenu(); ~QuicklaunchMenu(); protected: void contextMenuEvent(QContextMenuEvent*); }; class LeftAlignedTextStyle : public QProxyStyle { using QProxyStyle::QProxyStyle; public: virtual void drawItemText(QPainter * painter, const QRect & rect, int flags , const QPalette & pal, bool enabled, const QString & text , QPalette::ColorRole textRole = QPalette::NoRole) const override; }; class UKUITaskButton : public QToolButton { Q_OBJECT Q_PROPERTY(Qt::Corner origin READ origin WRITE setOrigin) public: explicit UKUITaskButton(QString appName,const WId window, UKUITaskBar * taskBar, QWidget *parent = 0); explicit UKUITaskButton(QString iconName, QString caption, const WId window, UKUITaskBar * taskbar, QWidget *parent = 0); UKUITaskButton(QuickLaunchAction * act, IUKUIPanelPlugin * plugin, QWidget* parent = 0); virtual ~UKUITaskButton(); bool isApplicationHidden() const; bool isApplicationActive() const; WId windowId() const { return mWindow; } bool hasUrgencyHint() const { return mUrgencyHint; } void setUrgencyHint(bool set); bool isOnDesktop(int desktop) const; bool isOnCurrentScreen() const; bool isMinimized() const; void updateText(); void setLeaderWindow(WId leaderWindow); bool isLeaderWindow(WId compare) { return mWindow == compare; } Qt::Corner origin() const; virtual void setAutoRotation(bool value, IUKUIPanel::Position position); UKUITaskBar * parentTaskBar() const {return mParentTaskBar;} void refreshIconGeometry(QRect const & geom); static QString mimeDataFormat() { return QLatin1String("ukui/UKUITaskButton"); } /*! \return true if this buttom received DragEnter event (and no DragLeave event yet) * */ bool hasDragAndDropHover() const; ///////////////////////////////// QHash settingsMap(); QString file_name; QString file; QString name; QString exec; void toDomodifyQuicklaunchMenuAction(bool direction) { modifyQuicklaunchMenuAction(direction);} bool isWinActivate; //1为激活状态,0为隐藏状态 QString mIconName; QString mCaption; public slots: void raiseApplication(); void minimizeApplication(); void maximizeApplication(); void deMaximizeApplication(); void shadeApplication(); void unShadeApplication(); void closeApplication(); void moveApplicationToDesktop(); void moveApplication(); void resizeApplication(); void setApplicationLayer(); void setOrigin(Qt::Corner); void updateIcon(); ////// void selfRemove(); void this_customContextMenuRequested(const QPoint & pos); void setGroupIcon(QIcon ico); protected: virtual void dragEnterEvent(QDragEnterEvent *event); virtual void dragMoveEvent(QDragMoveEvent * event); virtual void dragLeaveEvent(QDragLeaveEvent *event); virtual void dropEvent(QDropEvent *event); void mousePressEvent(QMouseEvent *event); virtual void mouseReleaseEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); virtual void contextMenuEvent(QContextMenuEvent *event); void enterEvent(QEvent *); void leaveEvent(QEvent *); void paintEvent(QPaintEvent *); void setWindowId(WId wid) {mWindow = wid;} virtual QMimeData * mimeData(); static bool sDraggging; inline IUKUIPanelPlugin * plugin() const { return mPlugin; } ///////////////////////////////////// //virtual QMimeData * mimeData(); private: bool statFlag = true; WId mWindow; QString mAppName; bool mUrgencyHint; QPoint mDragStartPosition; Qt::Corner mOrigin; QPixmap mPixmap; bool mDrawPixmap; UKUITaskBar * mParentTaskBar; IUKUIPanelPlugin * mPlugin; enum TaskButtonStatus{NORMAL, HOVER, PRESS}; TaskButtonStatus taskbuttonstatus; QIcon mIcon; // Timer for when draggind something into a button (the button's window // must be activated so that the use can continue dragging to the window QTimer * mDNDTimer; QGSettings *gsettings; /////////////////////////////////// QuickLaunchAction *mAct; QAction *mDeleteAct; QuicklaunchMenu *mMenu; QPoint mDragStart; TaskButtonStatus quicklanuchstatus; CustomStyle toolbuttonstyle; QGSettings *mgsettings; void modifyQuicklaunchMenuAction(bool direction); private slots: void activateWithDraggable(); signals: void dropped(QObject * dragSource, QPoint const & pos); void dragging(QObject * dragSource, QPoint const & pos); ////////////////////////////////// void buttonDeleted(); void switchButtons(UKUITaskButton *from, UKUITaskButton *to); void t_saveSettings(); }; class ButtonMimeData: public QMimeData { Q_OBJECT public: ButtonMimeData(): QMimeData(), mButton(0) { } UKUITaskButton *button() const { return mButton; } void setButton(UKUITaskButton *button) { mButton = button; } private: UKUITaskButton *mButton; }; //typedef QHash UKUITaskButtonHash; //typedef QHash UKUITaskButtonHash; #endif // UKUITASKBUTTON_H ukui-panel-3.0.6.4/plugin-taskbar/quicklaunchaction.h0000644000175000017500000000444514203402514021157 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2011 Razor team * Authors: * Petr Vanek * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef QUICKLAUNCHACTION_H #define QUICKLAUNCHACTION_H #include class XdgDesktopFile; /*! \brief Special action representation forUKUIQuickLaunch plugin. It supports XDG desktop files or "legacy" launching of specified apps. All process management is handled internally. \author Petr Vanek */ class QuickLaunchAction : public QAction { Q_OBJECT public: /*! Constructor for XDG desktop handlers. */ QuickLaunchAction(const XdgDesktopFile * xdg, QWidget * parent); //! Returns true if the action is valid (contains all required properties). bool isValid() { return m_valid; } QHash settingsMap() { return m_settingsMap; } /*! Returns list of additional actions to present for user (in menu). * Currently there are only "Addtitional application actions" for the ActionXdg type * (the [Desktop Action %s] in .desktop files) */ QList addtitionalActions() const { return m_addtitionalActions; } QHash m_settingsMap; QIcon getIconfromAction(); public slots: void execAction(QString additionalAction = QString{}); private: enum ActionType { ActionLegacy, ActionXdg, ActionFile }; ActionType m_type; QString m_data; bool m_valid; QList m_addtitionalActions; }; #endif ukui-panel-3.0.6.4/plugin-taskbar/ukuitaskbarplugin.h0000644000175000017500000000417414203402514021215 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2012 Razor team * 2014 LXQt team * Authors: * Alexander Sokoloff * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef UKUITASKBARPLUGIN_H #define UKUITASKBARPLUGIN_H #include "../panel/iukuipanel.h" #include "../panel/iukuipanelplugin.h" #include "ukuitaskbar.h" #include class UKUITaskBar; class UKUITaskBarPlugin : public QObject, public IUKUIPanelPlugin { Q_OBJECT public: UKUITaskBarPlugin(const IUKUIPanelPluginStartupInfo &startupInfo); ~UKUITaskBarPlugin(); QString themeId() const { return "TaskBar"; } virtual Flags flags() const { return HaveConfigDialog | NeedsHandle; } QWidget *widget() { return mTaskBar; } void realign(); bool isSeparate() const { return true; } bool isExpandable() const { return true; } private: UKUITaskBar *mTaskBar; QTranslator *m_translator; private: void translator(); }; class UKUITaskBarPluginLibrary: public QObject, public IUKUIPanelPluginLibrary { Q_OBJECT // Q_PLUGIN_METADATA(IID "ukui.org/Panel/PluginInterface/3.0") Q_INTERFACES(IUKUIPanelPluginLibrary) public: IUKUIPanelPlugin *instance(const IUKUIPanelPluginStartupInfo &startupInfo) const { return new UKUITaskBarPlugin(startupInfo);} }; #endif // UKUITASKBARPLUGIN_H ukui-panel-3.0.6.4/plugin-taskbar/ukuitaskwidget.h0000644000175000017500000001206114203402514020507 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include "../panel/iukuipanel.h" //#include #include #include #include #include #include class QPainter; class QPalette; class QMimeData; class UKUITaskGroup; class UKUITaskBar; class UKUITaskCloseButton; class UKUITaskWidget : public QWidget { Q_OBJECT Q_PROPERTY(Qt::Corner origin READ origin WRITE setOrigin) public: explicit UKUITaskWidget(const WId window, UKUITaskBar * taskBar, QWidget *parent = 0); explicit UKUITaskWidget(QString iconName, const WId window, UKUITaskBar * taskbar, QWidget *parent = 0); virtual ~UKUITaskWidget(); bool isApplicationHidden() const; bool isApplicationActive() const; WId windowId() const { return mWindow; } bool hasUrgencyHint() const { return mUrgencyHint; } void setUrgencyHint(bool set); bool isOnDesktop(int desktop) const; bool isOnCurrentScreen() const; bool isMinimized() const; bool isFocusState() const; void setThumbFixedSize(int w); void setThumbScale(bool val); void setThumbMaximumSize(int w); void updateText(); Qt::Corner origin() const; virtual void setAutoRotation(bool value, IUKUIPanel::Position position); UKUITaskBar * parentTaskBar() const {return mParentTaskBar;} void refreshIconGeometry(QRect const & geom); static QString mimeDataFormat() { return QLatin1String("ukui/UKUITaskWidget"); } /*! \return true if this buttom received DragEnter event (and no DragLeave event yet) * */ bool hasDragAndDropHover() const; void setThumbNail(QPixmap _pixmap); void setTitleFixedWidth(int size); void updateTitle(); void removeThumbNail(); void addThumbNail(); void setPixmap(QPixmap mPixmap); int getWidth(); QPixmap getPixmap(); void wl_updateTitle(QString caption); void wl_updateIcon(QString iconName); public slots: void raiseApplication(); void minimizeApplication(); void maximizeApplication(); void deMaximizeApplication(); void shadeApplication(); void unShadeApplication(); void closeApplication(); void moveApplicationToDesktop(); void moveApplication(); void resizeApplication(); void setApplicationLayer(); /** * @brief setWindowKeepAbove * 窗口置顶 */ void setWindowKeepAbove(); /** * @brief setWindowStatusClear * 取消置顶 */ void setWindowStatusClear(); void setOrigin(Qt::Corner); void updateIcon(); protected: virtual void dragEnterEvent(QDragEnterEvent *event); virtual void dragMoveEvent(QDragMoveEvent * event); virtual void dragLeaveEvent(QDragLeaveEvent *event); virtual void dropEvent(QDropEvent *event); void mousePressEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); void enterEvent(QEvent *); void leaveEvent(QEvent *); void paintEvent(QPaintEvent *); void contextMenuEvent(QContextMenuEvent *event); void setWindowId(WId wid) {mWindow = wid;} virtual QMimeData * mimeData(); static bool sDraggging; inline IUKUIPanelPlugin * plugin() const { return mPlugin; } private: NET::States stat; WId mWindow; bool mUrgencyHint; QPoint mDragStartPosition; Qt::Corner mOrigin; QPixmap mPixmap; bool mDrawPixmap; UKUITaskBar * mParentTaskBar; IUKUIPanelPlugin * mPlugin; QLabel *mTitleLabel; QLabel *mThumbnailLabel; QLabel *mAppIcon; UKUITaskCloseButton *mCloseBtn; QVBoxLayout *mVWindowsLayout; QHBoxLayout *mTopBarLayout; // Timer for when draggind something into a button (the button's window // must be activated so that the use can continue dragging to the window QTimer * mDNDTimer; enum TaskWidgetStatus{NORMAL, HOVER, PRESS}; TaskWidgetStatus status; bool taskWidgetPress; //按钮左键是否按下 bool isWaylandWidget = false; private slots: void activateWithDraggable(); void closeGroup(); signals: void dropped(QObject * dragSource, QPoint const & pos); void dragging(QObject * dragSource, QPoint const & pos); void windowMaximize(); void closeSigtoPop(); void closeSigtoGroup(); }; typedef QHash UKUITaskButtonHash; #endif // UKUITASKWIDGET_H ukui-panel-3.0.6.4/plugin-taskbar/ukuitaskbarplugin.cpp0000644000175000017500000000333214203402514021543 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2012 Razor team * 2014 LXQt team * Authors: * Alexander Sokoloff * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "ukuitaskbarplugin.h" UKUITaskBarPlugin::UKUITaskBarPlugin(const IUKUIPanelPluginStartupInfo &startupInfo): QObject(), IUKUIPanelPlugin(startupInfo) { translator(); mTaskBar = new UKUITaskBar(this); } UKUITaskBarPlugin::~UKUITaskBarPlugin() { delete mTaskBar; } void UKUITaskBarPlugin::realign() { mTaskBar->realign(); } void UKUITaskBarPlugin::translator(){ m_translator = new QTranslator(this); QString locale = QLocale::system().name(); if (locale == "zh_CN"){ if (m_translator->load(QM_INSTALL)) qApp->installTranslator(m_translator); else qDebug() < * Maciej Płaza * Kuzma Shapran * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef UKUITASKGROUP_H #define UKUITASKGROUP_H #include "../panel/iukuipanel.h" #include "../panel/iukuipanelplugin.h" #include "ukuitaskbar.h" #include "ukuigrouppopup.h" #include "ukuitaskwidget.h" #include "ukuitaskbutton.h" #include #include #include #include "../panel/ukuipanelpluginconfigdialog.h" #include "../panel/pluginsettings.h" #include //#include #define PREVIEW_WIDTH 468 #define PREVIEW_HEIGHT 428 #define SPACE_WIDTH 8 #define SPACE_HEIGHT 8 #define THUMBNAIL_WIDTH (PREVIEW_WIDTH - SPACE_WIDTH) #define THUMBNAIL_HEIGHT (PREVIEW_HEIGHT - SPACE_HEIGHT) #define ICON_WIDTH 48 #define ICON_HEIGHT 48 #define MAX_SIZE_OF_Thumb 16777215 #define SCREEN_MAX_WIDTH_SIZE 1400 #define SCREEN_MAX_HEIGHT_SIZE 1050 #define SCREEN_MIN_WIDTH_SIZE 800 #define SCREEN_MIN_HEIGHT_SIZE 600 #define SCREEN_MID_WIDTH_SIZE 1600 #define PREVIEW_WIDGET_MAX_WIDTH 352 #define PREVIEW_WIDGET_MAX_HEIGHT 264 #define PREVIEW_WIDGET_MIN_WIDTH 276 #define PREVIEW_WIDGET_MIN_HEIGHT 200 #define DEKSTOP_FILE_PATH "/usr/share/applications/" #define GET_DESKTOP_EXEC_NAME_MAIN "cat %s | awk '{if($1~\"Exec=\")if($2~\"\%\"){print $1} else print}' | cut -d '=' -f 2" #define GET_DESKTOP_EXEC_NAME_BACK "cat %s | awk '{if($1~\"StartupWMClass=\")print $1}' | cut -d '=' -f 2" #define GET_DESKTOP_ICON "cat %s | awk '{if($1~\"Icon=\")print $1}' | cut -d '=' -f 2" #define GET_PROCESS_EXEC_NAME_MAIN "ps -aux | sed 's/ \\+/ /g' |awk '{if($2~\"%d\")print}'| cut -d ' ' -f 11-" #define USR_SHARE_APP_CURRENT "/usr/share/applications/." #define USR_SHARE_APP_UPER "/usr/share/applications/.." #define PEONY_TRASH "/usr/share/applications/peony-trash.desktop" #define PEONY_COMUTER "/usr/share/applications/peony-computer.desktop" #define PEONY_HOME "/usr/share/applications/peony-home.desktop" #define PEONY_MAIN "/usr/share/applications/peony.desktop" class QVBoxLayout; class IUKUIPanelPlugin; class UKUIGroupPopup; class UKUiMasterPopup; class UKUITaskGroup: public UKUITaskButton { Q_OBJECT public: bool statFlag = true; bool existSameQckBtn = false; int QckBtnIndex = -1; bool hasbeenSaved = false; UKUITaskGroup(const QString & groupName, WId window, UKUITaskBar * parent); UKUITaskGroup(QuickLaunchAction * act, IUKUIPanelPlugin * plugin, UKUITaskBar *parent); UKUITaskGroup(const QString & iconName, const QString & caption, WId window, UKUITaskBar *parent = 0); virtual ~UKUITaskGroup(); QString groupName() const { return mGroupName; } int buttonsCount() const; int visibleButtonsCount() const; void initVisibleHash(); UKUITaskGroup* getOwnQckBtn() { return this->mpQckLchBtn; } QWidget * addWindow(WId id); bool onWindowChanged(WId window, NET::Properties prop, NET::Properties2 prop2); Qt::ToolButtonStyle popupButtonStyle() const; void setToolButtonsStyle(Qt::ToolButtonStyle style); void setPopupVisible(bool visible = true, bool fast = false); void removeWidget(); void removeSrollWidget(); bool isSetMaxWindow(); void showPreview(); int calcAverageWidth(); int calcAverageHeight(); void showAllWindowByList();//when number of window is more than 30,need show all window of app by a list void showAllWindowByThumbnail();//when number of window is no more than 30,need show all window of app by a thumbnail void singleWindowClick(); void VisibleWndRemoved(WId window); void setAutoRotation(bool value, IUKUIPanel::Position position); void setQckLchBtn(UKUITaskGroup *utgp) { if(statFlag) mpQckLchBtn = utgp; } UKUITaskGroup* getQckLchBtn() { return mpQckLchBtn; } void setActivateState_wl(bool _state); void wl_widgetUpdateTitle(QString caption); QWidget * wl_addWindow(WId id); bool CheckifWaylandGroup() {return isWaylandGroup;} public slots: void onWindowRemoved(WId window); void timeout(); void toDothis_customContextMenuRequested(const QPoint &pos); void onDesktopChanged(); protected: QMimeData * mimeData(); void leaveEvent(QEvent * event); void enterEvent(QEvent * event); void dragEnterEvent(QDragEnterEvent * event); void dragLeaveEvent(QDragLeaveEvent * event); void contextMenuEvent(QContextMenuEvent * event); void mouseMoveEvent(QMouseEvent * event); void mouseReleaseEvent(QMouseEvent *event); int recalculateFrameWidth() const; void setLayOutForPostion(); void draggingTimerTimeout(); private slots: void onClicked(bool checked); void onChildButtonClicked(); void onActiveWindowChanged(WId window); void closeGroup(); void refreshIconsGeometry(); void refreshVisibility(); void groupPopupShown(UKUITaskGroup* sender); void handleSavedEvent(); void AddtoTaskBar(); void RemovefromTaskBar(); signals: void groupBecomeEmpty(QString name); void groupHidden(QString name); void groupVisible(QString name, bool will); void visibilityChanged(bool visible); void popupShown(UKUITaskGroup* sender); void t_saveSettings(); void WindowAddtoTaskBar(QString arg); void WindowRemovefromTaskBar(QString arg); private: //bool isDesktopFile(QString urlName); UKUITaskBar * mParent; UKUITaskGroup *mpQckLchBtn; void changeTaskButtonStyle(); QString mGroupName; UKUIGroupPopup * mPopup; QVBoxLayout *VLayout; UKUITaskButtonHash mButtonHash; UKUITaskButtonHash mVisibleHash; bool mPreventPopup; bool mSingleButton; //!< flag if this group should act as a "standard" button (no groupping or only one "shown" window in group) enum TaskGroupStatus{NORMAL, HOVER, PRESS}; enum TaskGroupEvent{ENTEREVENT, LEAVEEVENT, OTHEREVENT}; TaskGroupStatus taskgroupStatus; TaskGroupEvent mTaskGroupEvent; QWidget *mpWidget; QScrollArea *mpScrollArea; QEvent * mEvent; QVector mShowInTurn; QTimer *mTimer; QSize recalculateFrameSize(); QPoint recalculateFramePosition(); void recalculateFrameIfVisible(); void adjustPopWindowSize(int width, int height); void v_adjustPopWindowSize(int width, int height, int v_all); void regroup(); QString isComputerOrTrash(QString urlName); void initDesktopFileName(int window); void initActionsInRightButtonMenu(); void badBackFunctionToFindDesktop(); void setBackIcon(); /////////////////////////////// // quicklaunch button QuickLaunchAction *mAct; IUKUIPanelPlugin * mPlugin; QAction *mDeleteAct; QuicklaunchMenu *mMenu; QPoint mDragStart; TaskGroupStatus quicklanuchstatus; CustomStyle toolbuttonstyle; QGSettings *mgsettings; bool isWaylandGroup; void winClickActivate_wl(bool _getActive); void closeGroup_wl(); }; #endif // UKUITASKGROUP_H ukui-panel-3.0.6.4/plugin-taskbar/ukuigrouppopup.cpp0000644000175000017500000001332214203402514021115 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2011 Razor team * 2014 LXQt team * Authors: * Alexander Sokoloff * Maciej Płaza * Kuzma Shapran * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "ukuigrouppopup.h" #include #include #include #include #include #include #include #include #include /************************************************ this class is just a container of window buttons the main purpose is showing window buttons in vertical layout and drag&drop feature inside group ************************************************/ UKUIGroupPopup::UKUIGroupPopup(UKUITaskGroup *group): QFrame(group), mGroup(group) { Q_ASSERT(group); setAcceptDrops(true); setWindowFlags(Qt::FramelessWindowHint | Qt::ToolTip); setAttribute(Qt::WA_AlwaysShowToolTips); setAttribute(Qt::WA_TranslucentBackground); setProperty("useSystemStyleBlur", true); setLayout(new QHBoxLayout); layout()->setSpacing(3); layout()->setMargin(0); rightclick = false; connect(&mCloseTimer, &QTimer::timeout, this, &UKUIGroupPopup::closeTimerSlot); mCloseTimer.setSingleShot(true); mCloseTimer.setInterval(400); setMaximumWidth(QApplication::screens().at(0)->size().width()); setMaximumHeight(QApplication::screens().at(0)->size().height()); } UKUIGroupPopup::~UKUIGroupPopup() { } void UKUIGroupPopup::dropEvent(QDropEvent *event) { qlonglong temp; QDataStream stream(event->mimeData()->data(UKUITaskButton::mimeDataFormat())); stream >> temp; WId window = (WId) temp; UKUITaskButton *button = nullptr; int oldIndex(0); // get current position of the button being dragged for (int i = 0; i < layout()->count(); i++) { UKUITaskButton *b = qobject_cast(layout()->itemAt(i)->widget()); if (b && b->windowId() == window) { button = b; oldIndex = i; break; } } if (button == nullptr) return; int newIndex = -1; // find the new position to place it in for (int i = 0; i < oldIndex && newIndex == -1; i++) { QWidget *w = layout()->itemAt(i)->widget(); if (w && w->pos().y() + w->height() / 2 > event->pos().y()) newIndex = i; } const int size = layout()->count(); for (int i = size - 1; i > oldIndex && newIndex == -1; i--) { QWidget *w = layout()->itemAt(i)->widget(); if (w && w->pos().y() + w->height() / 2 < event->pos().y()) newIndex = i; } if (newIndex == -1 || newIndex == oldIndex) return; QVBoxLayout * l = qobject_cast(layout()); l->takeAt(oldIndex); l->insertWidget(newIndex, button); l->invalidate(); } void UKUIGroupPopup::dragEnterEvent(QDragEnterEvent *event) { event->accept(); QWidget::dragEnterEvent(event); } void UKUIGroupPopup::dragLeaveEvent(QDragLeaveEvent *event) { hide(false/*not fast*/); QFrame::dragLeaveEvent(event); } /************************************************ * ************************************************/ void UKUIGroupPopup::leaveEvent(QEvent *event) { if (!rightclick) { QTimer::singleShot(300, this,SLOT(closeWindowDelay())); rightclick = false; } else { rightclick = false; } } /************************************************ * ************************************************/ void UKUIGroupPopup::enterEvent(QEvent *event) { QTimer::singleShot(300, this,SLOT(killTimerDelay())); // mCloseTimer.stop(); } void UKUIGroupPopup::killTimerDelay() { mCloseTimer.stop(); } void UKUIGroupPopup::closeWindowDelay() { if(mCloseTimer.isActive()) { mCloseTimer.stop(); } close(); } void UKUIGroupPopup::mousePressEvent(QMouseEvent *event) { if (event->button() == Qt::RightButton) rightclick = true; else rightclick = false; } void UKUIGroupPopup::paintEvent(QPaintEvent *event) { QPainter p(this); QStyleOption opt; opt.initFrom(this); p.setBrush(QBrush(QColor(0xff,0x14,0x14,0xb2))); style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); } void UKUIGroupPopup::hide(bool fast) { if (fast) close(); else mCloseTimer.start(); } void UKUIGroupPopup::show() { mCloseTimer.stop(); QFrame::show(); } void UKUIGroupPopup::closeTimerSlot() { bool button_has_dnd_hover = false; QLayout* l = layout(); for (int i = 0; l->count() > i; ++i) { UKUITaskWidget const * const button = dynamic_cast(l->itemAt(i)->widget()); if (0 != button && button->hasDragAndDropHover()) { button_has_dnd_hover = true; break; } } if (!button_has_dnd_hover) close(); } ukui-panel-3.0.6.4/plugin-taskbar/ukuitaskclosebutton.h0000644000175000017500000000221314203402514021563 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include class UKUITaskCloseButton : public QToolButton { Q_OBJECT public: explicit UKUITaskCloseButton(const WId window, QWidget *parent = 0); void mousePressEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event); private: WId mWindow; signals: void sigClicked(); }; #endif // UKUITASKCLOSEBUTTON_H ukui-panel-3.0.6.4/plugin-taskbar/resources/0000755000175000017500000000000014203402514017304 5ustar fengfengukui-panel-3.0.6.4/plugin-taskbar/resources/name-icon.match0000644000175000017500000001472314203402514022177 0ustar fengfengname=Apabi Reader ; icon=com.founder.apabi.reader name=斗鱼 ; icon=air.tv.douyu.android name=咪咕音乐 ; icon=cmccwm.mobilemusic name=新浪财经 ; icon=cn.; icon=com.sina.finance name=大麦 ; icon=cn.damai name=WPS ; icon=Office cn.wps.moffice_eng name=学习强国 ; icon=cn.xuexi.android name=铁路12306 ; icon=com.MobileTicket name=唯品会 ; icon=com.achievo.vipshop name=钉钉 ; icon=com.alibaba.android.rimet name=阿里云盘 ; icon=com.alicloud.databox name=百度网盘 ; icon=com.baidu.netdisk name=百度 ; icon=com.baidu.searchbox name=百度贴吧 ; icon=com.baidu.tieba name=菜鸟 ; icon=com.cainiao.wireless name=跳舞的线 ; icon=com.cmplay.dancingline name=汽车之家 ; icon=com.cubic.autohome name=每日瑜伽 ; icon=com.dailyyoga.cn name=大众点评 ; icon=com.dianping.v1 name=电视家 ; icon=com.dianshijia.tvlive name=豆瓣 ; icon=com.douban.frodo name=豆果美食 ; icon=com.douguo.recipe name=虎牙直播 ; icon=com.duowan.kiwi name=YY ; icon=com.duowan.mobile name=保卫萝卜3 ; icon=com.feiyu.carrot3 name=CAD看图王 ; icon=com.gstarmc.android name=开心消消乐® ; icon=com.happyelements.AndroidAnimal name=同花顺 ; icon=com.hexin.plat.android name=WeLink ; icon=com.huawei.welink name=芒果TV ; icon=com.hunantv.imgo.activity name=京东 ; icon=com.jingdong.app.mall name=前程无忧51job ; icon=com.job.android name=驾校一点通 ; icon=com.jxedt name=酷狗音乐 ; icon=com.kugou.android name=贝壳找房 ; icon=com.lianjia.beike name=蓝信+ ; icon=com.lite.lanxin name=流利说-英语 ; icon=com.liulishuo.engzo name=网易云音乐 ; icon=com.netease.cloudmusic name=网易邮箱 ; icon=com.netease.mobimail name=网易新闻 ; icon=com.netease.newsreader.activity name=向日葵远程控制 ; icon=com.oray.sunlogin name=我的汤姆猫 ; icon=com.outfit7.mytalkingtomfree name=汤姆猫跑酷 ; icon=com.outfit7.talkingtomgoldrun.wdj name=爱奇艺 ; icon=com.qiyi.video name=腾讯微云 ; icon=com.qq.qcloud name=欢乐麻将全集 ; icon=com.qqgame.happymj name=欢乐斗地主 ; icon=com.qqgame.hlddz name=美团 ; icon=com.sankuai.meituan name=网上国网 ; icon=com.sgcc.wsgw.cn name=得物(毒) ; icon=com.shizhuang.duapp name=新浪新闻 ; icon=com.sina.news name=绿洲 ; icon=com.sina.oasis name=微博 ; icon=com.sina.weibo name=快手 ; icon=com.smile.gifmaker name=今日头条 ; icon=com.ss.android.article.news name=西瓜视频 ; icon=com.ss.android.article.video name=懂车帝 ; icon=com.ss.android.auto name=抖音 ; icon=com.ss.android.ugc.aweme name=苏宁易购 ; icon=com.suning.mobile.ebuy name=皮皮虾 ; icon=com.sup.android.superb name=闲鱼 ; icon=com.taobao.idlefish name=飞猪旅行 ; icon=com.taobao.trip name=QQ邮箱 ; icon=com.tencent.androidqqmail name=腾讯课堂 ; icon=com.tencent.edu name=微信 ; icon=com.tencent.mm name=QQ ; icon=com.tencent.mobileqq name=QQ浏览器 ; icon=com.tencent.mtt name=腾讯新闻 ; icon=com.tencent.news name=天天爱消除 ; icon=com.tencent.peng name=欢乐升级 ; icon=com.tencent.qqgame.qqhlupwvga name=天天象棋 ; icon=com.tencent.qqgame.xq name=QQ极速版 ; icon=com.tencent.qqlite name=腾讯视频 ; icon=com.tencent.qqlive name=QQ音乐 ; icon=com.tencent.qqmusic name=腾讯体育 ; icon=com.tencent.qqsports name=和平精英 ; icon=com.tencent.tmgp.pubgmhd name=王者荣耀 ; icon=com.tencent.tmgp.sgame name=QQ飞车 ; icon=com.tencent.tmgp.speedmobile name=腾讯会议 ; icon=com.tencent.wemeet.app name=企业微信 ; icon=com.tencent.wework name=手机天猫 ; icon=com.tmall.wireless name=交管12123 ; icon=com.tmri.app.main name=航旅纵横 ; icon=com.umetrip.android.msky.app name=盒马 ; icon=com.wudaokou.hippo name=下厨房 ; icon=com.xiachufang name=香哈菜谱 ; icon=com.xiangha name=喜马拉雅 ; icon=com.ximalaya.ting.android name=小红书 ; icon=com.xingin.xhs name=迅雷 ; icon=com.xunlei.downloadprovider name=拼多多 ; icon=com.xunmeng.pinduoduo name=易车 ; icon=com.yiche.autoeasy name=印象笔记 ; icon=com.yinxiang name=网易有道词典 ; icon=com.youdao.dict name=有道云笔记 ; icon=com.youdao.note name=优酷视频 ; icon=com.youku.phone name=Gaaiho PDF ; icon=com.zeon.Gaaiho.Reader name=智联招聘 ; icon=com.zhaopin.social name=知乎 ; icon=com.zhihu.android name=携程旅行 ; icon=ctrip.android.view name=蜻蜓FM ; icon=fm.qingting.qtradio name=樊登读书 ; icon=io.dushu.fandengreader name=会见 ; iconorg.suirui.huijian.video name=哔哩哔哩 ; icon=tv.danmaku.bili name=i罗湖 ; icon=cn.gov.szlh.ilh name=福务通 ; icon=com.fdg.csp name=i深圳 ; icon=com.pingan.smt name=深圳天气 ; icon=com.sz.china.weather name=健康深圳 ; icon=com.xky.app.patient name=粤政易 ; icon=com.zwfw.YueZhengYi name=抖音极速版 ; icon=com.ss.android.ugc.aweme.lite name=今日头条极速版 ; icon=com.ss.android.article.lite name=快手极速版 ; icon=com.kuaishou.nebula name=百度极速版 ; icon=com.baidu.searchbox.lite name=爱奇艺极速版 ; icon=com.qiyi.video.lite name=喜马拉雅极速版 ; icon=com.ximalaya.ting.lite name=京东极速版 ; icon=com.jd.jdlite name=微博极速版 ; icon=com.sina.weibolite name=微博国际版 ; icon=com.weico.international name=贴吧极速版 ; icon=com.baidu.tieba_mini name=UC浏览器极速版 ; icon=com.ucmobile.lite name=斗鱼极速版 ; icon=com.douyu.rush name=皮皮虾极速版 ; icon=com.sup.android.slite name=驾考宝典极速版 icon=jiakaokesi.app.good name=驾校一点通极速版 ; icon=com.jxedtjsb name=汽车之家极速版 ; icon=com.autohome.speed name=易车极速版 ; icon=com.yiche.autofast name=央视影音 cn.cntv name=好信云会议 ; icon=com.lc.hx name=中国移动 ; icon=com.greenpoint.android.mc10086.activity name=中国联通 ; icon=com.sinovatech.unicom.ui name=中国建设银行 ; icon=com.chinamworld.main name=个人所得税 ; icon=cn.gov.tax.its name=手机天猫 ; icon=com.tmall.wireless name=美篇 ; icon=com.lanjingren.ivwen ukui-panel-3.0.6.4/plugin-taskbar/resources/taskbar.desktop.in0000644000175000017500000000026214203402514022733 0ustar fengfeng[Desktop Entry] Type=Service ServiceTypes=UKUIPanel/Plugin Name=Task manager Comment=Switch between running applications Icon=window-duplicate #TRANSLATIONS_DIR=../translations ukui-panel-3.0.6.4/plugin-taskbar/ukuitaskbar.h0000644000175000017500000002022114203402514017765 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2011 Razor team * 2014 LXQt team * Authors: * Alexander Sokoloff * Maciej Płaza * Kuzma Shapran * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef UKUITASKBAR_H #define UKUITASKBAR_H #include "../panel/iukuipanel.h" #include "../panel/iukuipanelplugin.h" #include "ukuitaskgroup.h" #include "ukuitaskbutton.h" #include #include #include //#include #include "../panel/iukuipanel.h" #include #include #include #include #include #include #include #include #include #include "qlayout.h" #include "qlayoutitem.h" #include "qlayoutitem.h" #include "qgridlayout.h" #include #include #include #include #include #include QT_BEGIN_NAMESPACE class QByteArray; template class QList; template class QMap; class QString; class QStringList; class QVariant; QT_END_NAMESPACE class XdgDesktopFile; class QuickLaunchAction; class QSettings; class QLabel; class QSignalMapper; class UKUITaskButton; class ElidedButtonStyle; class UKUITaskBarIcon; namespace UKUi { class GridLayout; } class UKUITaskBar : public QScrollArea { Q_OBJECT /* * 负责与ukui桌面环境应用通信的dbus * 在点击任务栏的时候发给其他UKUI DE APP 点击信号 * 以适应特殊的设计需求以及    */ Q_CLASSINFO("D-Bus Interface", "com.ukui.panel.plugins.taskbar") public: explicit UKUITaskBar(IUKUIPanelPlugin *plugin, QWidget* parent = 0); virtual ~UKUITaskBar(); void realign(); Qt::ToolButtonStyle buttonStyle() const { return mButtonStyle; } int buttonWidth() const { return mButtonWidth; } bool closeOnMiddleClick() const { return mCloseOnMiddleClick; } bool raiseOnCurrentDesktop() const { return mRaiseOnCurrentDesktop; } bool isShowOnlyOneDesktopTasks() const { return mShowOnlyOneDesktopTasks; } int showDesktopNum() const { return mShowDesktopNum; } bool getCpuInfoFlg() const { return CpuInfoFlg; } bool isShowOnlyCurrentScreenTasks() const { return mShowOnlyCurrentScreenTasks; } bool isShowOnlyMinimizedTasks() const { return mShowOnlyMinimizedTasks; } bool isAutoRotate() const { return mAutoRotate; } bool isGroupingEnabled() const { return mGroupingEnabled; } bool isShowGroupOnHover() const { return mShowGroupOnHover; } bool isIconByClass() const { return mIconByClass; } void setShowGroupOnHover(bool bFlag); inline IUKUIPanel * panel() const { return mPlugin->panel(); } inline IUKUIPanelPlugin * plugin() const { return mPlugin; } inline UKUITaskBarIcon* fetchIcon()const{return mpTaskBarIcon;} void pubAddButton(QuickLaunchAction* action) { addButton(action); } void pubSaveSettings() { saveSettings(); } //////////////////////////////////////////////// /// \brief quicklaunch func /// int indexOfButton(UKUITaskGroup *button) const; int countOfButtons() const; //virtual QLayoutItem *takeAt(int index) = 0; void saveSettings(); void refreshQuickLaunch(); friend class FilectrlAdaptor; QStringList mIgnoreWindow; signals: void buttonRotationRefreshed(bool autoRotate, IUKUIPanel::Position position); void buttonStyleRefreshed(Qt::ToolButtonStyle buttonStyle); void refreshIconGeometry(); void showOnlySettingChanged(); void iconByClassChanged(); void popupShown(UKUITaskGroup* sender); void sendToUkuiDEApp(void); //quicklaunch void setsizeoftaskbarbutton(int _size); protected: virtual void dragEnterEvent(QDragEnterEvent * event); virtual void dragMoveEvent(QDragMoveEvent * event); void enterEvent(QEvent *); void leaveEvent(QEvent *); void paintEvent(QPaintEvent *); void mousePressEvent(QMouseEvent *); void mouseMoveEvent(QMouseEvent *e); void dropEvent(QDropEvent *e); private slots: void refreshTaskList(); void refreshButtonRotation(); void refreshPlaceholderVisibility(); void groupBecomeEmptySlot(); void saveSettingsSlot(); void onWindowChanged(WId window, NET::Properties prop, NET::Properties2 prop2); void onWindowAdded(WId window); void onWindowRemoved(WId window); void activateTask(int pos); void DosaveSettings() { saveSettings(); } void onDesktopChanged(); //////////////////////////// /// quicklaunch slots /// bool checkButton(QuickLaunchAction* action); void removeButton(QuickLaunchAction* action); void removeButton(QString exec); void buttonDeleted(); void removeFromTaskbar(QString arg); void switchButtons(UKUITaskGroup *dst_button, UKUITaskGroup *src_button); QString readFile(const QString &filename); void _AddToTaskbar(QString arg); void wl_kwinSigHandler(quint32 wl_winId, int opNo, QString wl_iconName, QString wl_caption); bool isFileExit(const QString &filename); private: typedef QMap windowMap_t; private: void addWindow(WId window); void addButton(QuickLaunchAction* action); windowMap_t::iterator removeWindow(windowMap_t::iterator pos); void buttonMove(UKUITaskGroup * dst, UKUITaskGroup * src, QPoint const & pos); void doInitGroupButton(QString sname); void initRelationship(); enum TaskStatus{NORMAL, HOVER, PRESS}; TaskStatus taskstatus; //////////////////////////////////// /// quicklaunch parameter QVector mVBtn; QGSettings *settings; QToolButton *pageup; QToolButton *pagedown; QWidget *tmpwidget; QVector mBtnAll; QVector mBtncvd; private: QMap mKnownWindows; //!< Ids of known windows (mapping to buttons/groups) QList swid; UKUi::GridLayout *mLayout; // QList mKeys; QSignalMapper *mSignalMapper; // Settings Qt::ToolButtonStyle mButtonStyle; int mButtonWidth; int mButtonHeight; bool CpuInfoFlg = true; bool mCloseOnMiddleClick; bool mRaiseOnCurrentDesktop; bool mShowOnlyOneDesktopTasks; int mShowDesktopNum; bool mShowOnlyCurrentScreenTasks; bool mShowOnlyMinimizedTasks; bool mAutoRotate; bool mGroupingEnabled; bool mShowGroupOnHover; bool mIconByClass; bool mCycleOnWheelScroll; //!< flag for processing the wheelEvent bool acceptWindow(WId window) const; void setButtonStyle(Qt::ToolButtonStyle buttonStyle); void settingsChanged(); QList > copyQuicklaunchConfig(); void wheelEvent(QWheelEvent* event); void changeEvent(QEvent* event); void resizeEvent(QResizeEvent *event); IUKUIPanelPlugin *mPlugin; LeftAlignedTextStyle *mStyle; UKUITaskBarIcon *mpTaskBarIcon; QWidget *mAllFrame; QWidget *mPlaceHolder; QGSettings *changeTheme; QHash mAndroidIconHash; QHash matchAndroidIcon(); QString captionExchange(QString str); void addWindow_wl(QString iconName, QString caption, WId window); public slots: void WindowAddtoTaskBar(QString arg); void WindowRemovefromTaskBar(QString arg); }; #endif // UKUITASKBAR_H ukui-panel-3.0.6.4/plugin-taskbar/CMakeLists.txt0000644000175000017500000000217314204636776020061 0ustar fengfengset(PLUGIN "taskbar") set(HEADERS ukuitaskbar.h ukuitaskbutton.h ukuitaskbarplugin.h ukuitaskgroup.h ukuigrouppopup.h ukuitaskwidget.h ukuitaskclosebutton.h quicklaunchaction.h ) set(SOURCES ukuitaskbar.cpp ukuitaskbutton.cpp ukuitaskbarplugin.cpp ukuitaskgroup.cpp ukuigrouppopup.cpp ukuitaskwidget.cpp ukuitaskclosebutton.cpp quicklaunchaction.cpp ) find_package(X11 REQUIRED) find_package(PkgConfig) pkg_check_modules(GIOUNIX2 REQUIRED gio-unix-2.0) pkg_check_modules(GLIB2 REQUIRED glib-2.0 gio-2.0) include_directories(${GLIB2_INCLUDE_DIRS}) #for include_directories(${_Qt5DBus_OWN_INCLUDE_DIRS}) include_directories( ${UKUI_INCLUDE_DIRS} "${CMAKE_CURRENT_SOURCE_DIR}/../panel" ${GIOUNIX2_INCLUDE_DIRS} ) set(LIBRARIES Qt5Xdg ${GIOUNIX2_LIBRARIES} ${X11_LIBRARIES} Qt5X11Extras ) install(FILES resources/name-icon.match DESTINATION "/usr/share/ukui/ukui-panel/plugin-taskbar" COMPONENT Runtime ) include(../cmake/UkuiPluginTranslationTs.cmake) ukui_plugin_translate_ts(${PLUGIN}) BUILD_UKUI_PLUGIN(${PLUGIN}) ukui-panel-3.0.6.4/plugin-taskbar/ukuitaskgroup.cpp0000644000175000017500000013575714203402514020735 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2011 Razor team * 2014 LXQt team * Authors: * Alexander Sokoloff * Maciej Płaza * Kuzma Shapran * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "ukuitaskgroup.h" #include "ukuitaskbar.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../panel/iukuipanelplugin.h" #include "../panel/highlight-effect.h" #include #include #include #include #include #include "../panel/customstyle.h" #define UKUI_PANEL_SETTINGS "org.ukui.panel.settings" #define PANELPOSITION "panelposition" #define UKUI_PANEL_DAEMON "org.ukui.panel.daemon" #define UKUI_PANEL_DAEMON_PATH "/convert/desktopwid" #define UKUI_PANEL_DAEMON_INTERFACE "org.ukui.panel.daemon" #define UKUI_PANEL_DAEMON_METHOD "WIDToDesktop" #define WAYLAND_GROUP_HIDE 0 #define WAYLAND_GROUP_ACTIVATE 1 #define WAYLAND_GROUP_CLOSE 2 QPixmap qimageFromXImage(XImage* ximage) { QImage::Format format = QImage::Format_ARGB32_Premultiplied; if (ximage->depth == 24) format = QImage::Format_RGB32; else if (ximage->depth == 16) format = QImage::Format_RGB16; QImage image = QImage(reinterpret_cast(ximage->data), ximage->width, ximage->height, ximage->bytes_per_line, format).copy(); // 大端还是小端? if ((QSysInfo::ByteOrder == QSysInfo::LittleEndian && ximage->byte_order == MSBFirst) || (QSysInfo::ByteOrder == QSysInfo::BigEndian && ximage->byte_order == LSBFirst)) { for (int i = 0; i < image.height(); i++) { if (ximage->depth == 16) { ushort* p = reinterpret_cast(image.scanLine(i)); ushort* end = p + image.width(); while (p < end) { *p = ((*p << 8) & 0xff00) | ((*p >> 8) & 0x00ff); p++; } } else { uint* p = reinterpret_cast(image.scanLine(i)); uint* end = p + image.width(); while (p < end) { *p = ((*p << 24) & 0xff000000) | ((*p << 8) & 0x00ff0000) | ((*p >> 8) & 0x0000ff00) | ((*p >> 24) & 0x000000ff); p++; } } } } // 修复alpha通道 if (format == QImage::Format_RGB32) { QRgb* p = reinterpret_cast(image.bits()); for (int y = 0; y < ximage->height; ++y) { for (int x = 0; x < ximage->width; ++x) p[x] |= 0xff000000; p += ximage->bytes_per_line / 4; } } return QPixmap::fromImage(image); } /************************************************ ************************************************/ UKUITaskGroup::UKUITaskGroup(QuickLaunchAction * act, IUKUIPanelPlugin * plugin, UKUITaskBar * parent) : UKUITaskButton(act, plugin, parent), mPlugin(plugin), mAct(act), mParent(parent) { statFlag = false; setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); setAcceptDrops(true); /*设置快速启动栏的按键不接受焦点*/ setFocusPolicy(Qt::NoFocus); setAutoRaise(true); quicklanuchstatus = NORMAL; setDefaultAction(mAct); mAct->setParent(this); /*设置快速启动栏的菜单项*/ const QByteArray id(UKUI_PANEL_SETTINGS); mgsettings = new QGSettings(id); toDomodifyQuicklaunchMenuAction(true); connect(mgsettings, &QGSettings::changed, this, [=] (const QString &key){ if(key==PANELPOSITION){ toDomodifyQuicklaunchMenuAction(true); } }); setContextMenuPolicy(Qt::CustomContextMenu); file_name=act->m_settingsMap["desktop"]; file = act->m_settingsMap["file"]; exec = act->m_settingsMap["exec"]; name = act->m_settingsMap["name"]; this->setStyle(new CustomStyle()); repaint(); } UKUITaskGroup::UKUITaskGroup(const QString &groupName, WId window, UKUITaskBar *parent) : UKUITaskButton(groupName,window, parent, parent), mGroupName(groupName), mPopup(new UKUIGroupPopup(this)), mPreventPopup(false), mSingleButton(true), mTimer(new QTimer(this)), mpWidget(NULL), mParent(parent), isWaylandGroup(false) { Q_ASSERT(parent); mpScrollArea = NULL; taskgroupStatus = NORMAL; initDesktopFileName(window); initActionsInRightButtonMenu(); connect(this, SIGNAL(clicked(bool)), this, SLOT(onClicked(bool))); connect(KWindowSystem::self(), SIGNAL(activeWindowChanged(WId)), this, SLOT(onActiveWindowChanged(WId))); connect(parent, &UKUITaskBar::refreshIconGeometry, this, &UKUITaskGroup::refreshIconsGeometry); connect(parent, &UKUITaskBar::buttonStyleRefreshed, this, &UKUITaskGroup::setToolButtonsStyle); connect(parent, &UKUITaskBar::showOnlySettingChanged, this, &UKUITaskGroup::refreshVisibility); connect(parent, &UKUITaskBar::popupShown, this, &UKUITaskGroup::groupPopupShown); mTimer->setTimerType(Qt::PreciseTimer); connect(mTimer, SIGNAL(timeout()), SLOT(timeout())); } UKUITaskGroup::UKUITaskGroup(const QString & iconName, const QString & caption, WId window, UKUITaskBar *parent) : UKUITaskButton(iconName, caption, window, parent, parent), mTimer(new QTimer(this)), mPopup(new UKUIGroupPopup(this)), mPreventPopup(false), mpWidget(NULL), mSingleButton(false), isWaylandGroup(true) { //setObjectName(caption); //setText(caption); Q_ASSERT(parent); mIconName=iconName; taskgroupStatus = NORMAL; isWinActivate = true; setIcon(QIcon::fromTheme(iconName)); connect(this, SIGNAL(clicked(bool)), this, SLOT(onClicked(bool))); connect(parent, &UKUITaskBar::buttonStyleRefreshed, this, &UKUITaskGroup::setToolButtonsStyle); //connect(parent, &UKUITaskBar::showOnlySettingChanged, this, &UKUITaskGroup::refreshVisibility); connect(parent, &UKUITaskBar::popupShown, this, &UKUITaskGroup::groupPopupShown); mTimer->setTimerType(Qt::PreciseTimer); connect(mTimer, SIGNAL(timeout()), SLOT(timeout())); } UKUITaskGroup::~UKUITaskGroup() { } void UKUITaskGroup::initDesktopFileName(int window) { QDBusInterface iface(UKUI_PANEL_DAEMON, UKUI_PANEL_DAEMON_PATH, UKUI_PANEL_DAEMON_INTERFACE, QDBusConnection::sessionBus()); QDBusReply reply = iface.call(UKUI_PANEL_DAEMON_METHOD, window); QString processExeName = reply.value(); if (!processExeName.isEmpty()) { file_name = processExeName; } } void UKUITaskGroup::initActionsInRightButtonMenu(){ if (file_name.isEmpty()) return; const auto url=QUrl(file_name); QString fileName(url.isLocalFile() ? url.toLocalFile() : url.url()); XdgDesktopFile xdg; if (xdg.load(fileName)){ mAct = new QuickLaunchAction(&xdg, this); setGroupIcon(mAct->getIconfromAction()); } } void UKUITaskGroup::contextMenuEvent(QContextMenuEvent *event) { setPopupVisible(false, true); mPreventPopup = true; if (mSingleButton && !isWaylandGroup) { UKUITaskButton::contextMenuEvent(event); return; } QMenu * menu = new QMenu(tr("Group")); menu->setAttribute(Qt::WA_DeleteOnClose); if (!file_name.isEmpty()) { menu->addAction(mAct); menu->addActions(mAct->addtitionalActions()); menu->addSeparator(); menu->addSeparator(); QAction *mDeleteAct = menu->addAction(HighLightEffect::drawSymbolicColoredIcon(QIcon::fromTheme("ukui-unfixed")), tr("delete from taskbar")); connect(mDeleteAct, SIGNAL(triggered()), this, SLOT(RemovefromTaskBar())); QAction *mAddAct = menu->addAction(HighLightEffect::drawSymbolicColoredIcon(QIcon::fromTheme("ukui-fixed")), tr("add to taskbar")); connect(mAddAct, SIGNAL(triggered()), this, SLOT(AddtoTaskBar())); if (existSameQckBtn) menu->removeAction(mAddAct); else menu->removeAction(mDeleteAct); } QAction *mCloseAct = menu->addAction(QIcon::fromTheme("application-exit-symbolic"), tr("close")); connect(mCloseAct, SIGNAL(triggered()), this, SLOT(closeGroup())); connect(menu, &QMenu::aboutToHide, [this] { mPreventPopup = false; }); menu->setGeometry(plugin()->panel()->calculatePopupWindowPos(mapToGlobal(event->pos()), menu->sizeHint())); plugin()->willShowWindow(menu); menu->show(); } void UKUITaskGroup::RemovefromTaskBar() { emit WindowRemovefromTaskBar(file_name); } void UKUITaskGroup::AddtoTaskBar() { emit WindowAddtoTaskBar(groupName()); } /************************************************ ************************************************/ void UKUITaskGroup::closeGroup() { if (isWaylandGroup) { closeGroup_wl(); return; } #if (QT_VERSION < QT_VERSION_CHECK(5,7,0)) for(auto it=mButtonHash.begin();it!=mButtonHash.end();it++) { UKUITaskWidget *button =it.value(); if (button->isOnDesktop(KWindowSystem::currentDesktop())) button->closeApplication(); } #else for (UKUITaskWidget *button : qAsConst(mButtonHash) ) if (button->isOnDesktop(KWindowSystem::currentDesktop())) button->closeApplication(); #endif } /************************************************ ************************************************/ QWidget * UKUITaskGroup::addWindow(WId id) { if (mButtonHash.contains(id)) return mButtonHash.value(id); UKUITaskWidget *btn = new UKUITaskWidget(id, parentTaskBar(), mPopup); mButtonHash.insert(id, btn); connect(btn, SIGNAL(clicked()), this, SLOT(onChildButtonClicked())); connect(btn, SIGNAL(windowMaximize()), this, SLOT(onChildButtonClicked())); refreshVisibility(); changeTaskButtonStyle(); return btn; } /*changeTaskButtonStyle in class UKUITaskGroup not class UKUITaskButton * because class UKUITaskButton can not get mButtonHash.size */ void UKUITaskGroup::changeTaskButtonStyle() { if(mVisibleHash.size()>1) this->setStyle(new CustomStyle("taskbutton",true)); else this->setStyle(new CustomStyle("taskbutton",false)); } void UKUITaskGroup::onActiveWindowChanged(WId window) { UKUITaskWidget *button = mButtonHash.value(window, nullptr); // for (QWidget *btn : qAsConst(mButtonHash)) // btn->setChecked(false); // if (button) // { // button->setChecked(true); // if (button->hasUrgencyHint()) // button->setUrgencyHint(false); // } setChecked(nullptr != button); } /************************************************ ************************************************/ void UKUITaskGroup::onDesktopChanged() { refreshVisibility(); changeTaskButtonStyle(); } /************************************************ ************************************************/ void UKUITaskGroup::onWindowRemoved(WId window) { if (mButtonHash.contains(window)) { UKUITaskWidget *button = mButtonHash.value(window); mButtonHash.remove(window); if (mVisibleHash.contains(window)) { mShowInTurn.removeOne(mVisibleHash.value(window)); mVisibleHash.remove(window); } mPopup->removeWidget(button); button->deleteLater(); if (!parentTaskBar()->getCpuInfoFlg()) system(QString("rm -f /tmp/%1.png").arg(window).toLatin1()); if (isLeaderWindow(window) && (mShowInTurn.size() > 0)) setLeaderWindow(mButtonHash.key(mShowInTurn.at(0))); if (mButtonHash.count()) { if(mPopup->isVisible()) { // mPopup->hide(true); showPreview(); } else { regroup(); } } else { if (isVisible()) emit visibilityChanged(false); hide(); emit groupBecomeEmpty(groupName()); } changeTaskButtonStyle(); } } /************************************************ ************************************************/ void UKUITaskGroup::onChildButtonClicked() { setPopupVisible(false, true); parentTaskBar()->setShowGroupOnHover(true); //QToolButton::leaveEvent(event); taskgroupStatus = NORMAL; update(); } /************************************************ ************************************************/ Qt::ToolButtonStyle UKUITaskGroup::popupButtonStyle() const { // do not set icons-only style in the buttons in the group, // as they'll be indistinguishable const Qt::ToolButtonStyle style = toolButtonStyle(); return style == Qt::ToolButtonIconOnly ? Qt::ToolButtonTextBesideIcon : style; } /************************************************ ************************************************/ void UKUITaskGroup::setToolButtonsStyle(Qt::ToolButtonStyle style) { setToolButtonStyle(style); // const Qt::ToolButtonStyle styleInPopup = popupButtonStyle(); // for (auto & button : mButtonHash) // { // button->setToolButtonStyle(styleInPopup); // } } /************************************************ ************************************************/ int UKUITaskGroup::buttonsCount() const { return mButtonHash.count(); } void UKUITaskGroup::initVisibleHash() { /* for (UKUITaskButtonHash::const_iterator it = mButtonHash.begin();it != mButtonHash.end();it++) { if (mVisibleHash.contains(it.key())) continue; if (it.value()->isVisibleTo(mPopup)) mVisibleHash.insert(it.key(), it.value()); }*/ } /************************************************ ************************************************/ int UKUITaskGroup::visibleButtonsCount() const { int i = 0; #if (QT_VERSION < QT_VERSION_CHECK(5,7,0)) for (auto it=mButtonHash.begin();it!=mButtonHash.end();it++) { UKUITaskWidget *btn=it.value(); if (btn->isVisibleTo(mPopup)) i++; } #else for (UKUITaskWidget *btn : qAsConst(mButtonHash)) if (btn->isVisibleTo(mPopup)) i++; #endif return i; } /************************************************ ************************************************/ void UKUITaskGroup::draggingTimerTimeout() { if (mSingleButton) setPopupVisible(false); } /************************************************ ************************************************/ void UKUITaskGroup::onClicked(bool) { if (isWaylandGroup) { winClickActivate_wl(!isWinActivate); return; } if (1 == mVisibleHash.size()) { return singleWindowClick(); } if(mPopup->isVisible()) { if(HOVER == taskgroupStatus) { taskgroupStatus = NORMAL; return; } else { mPopup->hide(); return; } } else { showPreview(); } mTaskGroupEvent = OTHEREVENT; if(mTimer->isActive()) { mTimer->stop(); } } void UKUITaskGroup::singleWindowClick() { UKUITaskWidget *btn = mVisibleHash.begin().value(); if(btn) { if(!btn->isFocusState() || btn->isMinimized()) { if(mPopup->isVisible()) { mPopup->hide(); } KWindowSystem::forceActiveWindow(mVisibleHash.begin().key()); } else { btn->minimizeApplication(); if(mPopup->isVisible()) { mPopup->hide(); } } } mTaskGroupEvent = OTHEREVENT; if(mTimer->isActive()) { mTimer->stop(); } } /************************************************ ************************************************/ void UKUITaskGroup::regroup() { int cont = visibleButtonsCount(); recalculateFrameIfVisible(); // if (cont == 1) // { // mSingleButton = false; // // Get first visible button // UKUITaskButton * button = NULL; // for (UKUITaskButton *btn : qAsConst(mButtonHash)) // { // if (btn->isVisibleTo(mPopup)) // { // button = btn; // break; // } // } // if (button) // { // setText(button->text()); // setToolTip(button->toolTip()); // setWindowId(button->windowId()); // } // } /*else*/ if (cont == 0) { // emit groupHidden(groupName()); hide(); } else { mSingleButton = false; QString t = QString("%1 - %2 windows").arg(mGroupName).arg(cont); setText(t); setToolTip(parentTaskBar()->isShowGroupOnHover() ? QString() : t); } } /************************************************ ************************************************/ void UKUITaskGroup::recalculateFrameIfVisible() { if (mPopup->isVisible()) { recalculateFrameSize(); if (plugin()->panel()->position() == IUKUIPanel::PositionBottom) recalculateFramePosition(); } } /************************************************ ************************************************/ void UKUITaskGroup::setAutoRotation(bool value, IUKUIPanel::Position position) { // for (QWidget *button : qAsConst(mButtonHash)) // button->setAutoRotation(false, position); //UKUITaskWidget::setAutoRotation(value, position); } /************************************************ ************************************************/ void UKUITaskGroup::refreshVisibility() { bool will = false; UKUITaskBar const * taskbar = parentTaskBar(); const int showDesktop = taskbar->showDesktopNum(); for(UKUITaskButtonHash::const_iterator i=mButtonHash.begin();i!=mButtonHash.end();i++) { UKUITaskWidget * btn=i.value(); bool visible = taskbar->isShowOnlyOneDesktopTasks() ? btn->isOnDesktop(0 == showDesktop ? KWindowSystem::currentDesktop() : showDesktop) : true; visible &= taskbar->isShowOnlyCurrentScreenTasks() ? btn->isOnCurrentScreen() : true; visible &= taskbar->isShowOnlyMinimizedTasks() ? btn->isMinimized() : true; btn->setVisible(visible); if (btn->isVisibleTo(mPopup) && !mVisibleHash.contains(i.key())) { mVisibleHash.insert(i.key(), i.value()); mShowInTurn.push_back(i.value()); } else if (!btn->isVisibleTo(mPopup) && mVisibleHash.contains(i.key())) { mVisibleHash.remove(i.key()); mShowInTurn.removeOne(i.value()); } will |= visible; } if (!mShowInTurn.isEmpty()) setLeaderWindow(mVisibleHash.key(mShowInTurn.at(0))); bool is = isVisible(); // emit groupVisible(groupName(), will); // else setVisible(will); // will &= this->isVisible(); setVisible(will); if (this->existSameQckBtn) mpQckLchBtn->setHidden(will); if(!mPopup->isVisible()) { regroup(); } if (is != will) emit visibilityChanged(will); } /************************************************ ************************************************/ QMimeData * UKUITaskGroup::mimeData() { QMimeData *mimedata = new QMimeData; QByteArray byteArray; QDataStream stream(&byteArray, QIODevice::WriteOnly); stream << groupName(); mimedata->setData(mimeDataFormat(), byteArray); return mimedata; } /************************************************ ************************************************/ void UKUITaskGroup::setPopupVisible(bool visible, bool fast) { if (!statFlag) return; if (visible && !mPreventPopup && !mSingleButton) { // QTimer::singleShot(400, this,SLOT(showPreview())); showPreview(); /* for origin preview plugin()->willShowWindow(mPopup); mPopup->show(); qDebug()<<"setPopupVisible ********"; emit popupShown(this);*/ } else mPopup->hide(fast); } /************************************************ ************************************************/ void UKUITaskGroup::refreshIconsGeometry() { float scale = qApp->devicePixelRatio(); QRect rect = geometry(); rect.moveTo(mapToGlobal(QPoint(0, 0)).x() * scale, mapToGlobal(QPoint(0, 0)).y() * scale); if (mSingleButton) { refreshIconGeometry(rect); return; } for(UKUITaskWidget *but : qAsConst(mButtonHash)) { but->refreshIconGeometry(rect); // but->setIconSize(QSize(plugin()->panel()->iconSize(), plugin()->panel()->iconSize())); } } /************************************************ ************************************************/ QSize UKUITaskGroup::recalculateFrameSize() { int height = 120; mPopup->setMaximumHeight(1000); mPopup->setMinimumHeight(0); int hh = recalculateFrameWidth(); mPopup->setMaximumWidth(hh); mPopup->setMinimumWidth(0); QSize newSize(hh, height); mPopup->resize(newSize); return newSize; } int UKUITaskGroup::recalculateFrameWidth() const { const QFontMetrics fm = fontMetrics(); int max = 100 * fm.width (' '); // elide after the max width int txtWidth = 0; // for (UKUITaskButton *btn : qAsConst(mButtonHash)) // txtWidth = qMax(fm.width(btn->text()), txtWidth); return iconSize().width() + qMin(txtWidth, max) + 30/* give enough room to margins and borders*/; } void UKUITaskGroup::toDothis_customContextMenuRequested(const QPoint & pos) { mPlugin->willShowWindow(mMenu); mMenu->popup(mPlugin->panel()->calculatePopupWindowPos(mapToGlobal({0, 0}), mMenu->sizeHint()).topLeft()); } /************************************************ ************************************************/ QPoint UKUITaskGroup::recalculateFramePosition() { // Set position int x_offset = 0, y_offset = 0; switch (plugin()->panel()->position()) { case IUKUIPanel::PositionTop: y_offset += height(); break; case IUKUIPanel::PositionBottom: y_offset = -120; break; case IUKUIPanel::PositionLeft: x_offset += width(); break; case IUKUIPanel::PositionRight: x_offset = -recalculateFrameWidth(); break; } QPoint pos = mapToGlobal(QPoint(x_offset, y_offset)); mPopup->move(pos); return pos; } void UKUITaskGroup::leaveEvent(QEvent *event) { //QTimer::singleShot(300, this,SLOT(mouseLeaveOut())); mTaskGroupEvent = LEAVEEVENT; if (!statFlag) { update(); return; } mEvent = event; if(mTimer->isActive()) { mTimer->stop();//stay time is no more than 400 ms need kill timer } else { mTimer->start(300); } } void UKUITaskGroup::enterEvent(QEvent *event) { //QToolButton::enterEvent(event); mTaskGroupEvent = ENTEREVENT; if (!statFlag) { update(); return; } mEvent = event; mTimer->start(400); } void UKUITaskGroup::handleSavedEvent() { if (sDraggging) return; if (!statFlag) return; if (statFlag && parentTaskBar()->isShowGroupOnHover()) { setPopupVisible(true); } taskgroupStatus = HOVER; repaint(); QToolButton::enterEvent(mEvent); } void UKUITaskGroup::dragEnterEvent(QDragEnterEvent *event) { // only show the popup if we aren't dragging a taskgroup if (!event->mimeData()->hasFormat(mimeDataFormat())) { setPopupVisible(true); } UKUITaskButton::dragEnterEvent(event); } void UKUITaskGroup::mouseReleaseEvent(QMouseEvent *event) { // only show the popup if we aren't dragging a taskgroup UKUITaskButton::mouseReleaseEvent(event); } /************************************************ ************************************************/ void UKUITaskGroup::dragLeaveEvent(QDragLeaveEvent *event) { // if draggind something into the taskgroup or the taskgroups' popup, // do not close the popup if (!sDraggging) setPopupVisible(false); UKUITaskButton::dragLeaveEvent(event); } void UKUITaskGroup::mouseMoveEvent(QMouseEvent* event) { // if dragging the taskgroup, do not show the popup setPopupVisible(false, true); UKUITaskButton::mouseMoveEvent(event); } /************************************************ ************************************************/ bool UKUITaskGroup::onWindowChanged(WId window, NET::Properties prop, NET::Properties2 prop2) { // returns true if the class is preserved bool needsRefreshVisibility{false}; QVector buttons; if (mButtonHash.contains(window)) buttons.append(mButtonHash.value(window)); // If group is based on that window properties must be changed also on button group if (window == windowId()) buttons.append(this); if (!buttons.isEmpty()) { // if class is changed the window won't belong to our group any more if (parentTaskBar()->isGroupingEnabled() && prop2.testFlag(NET::WM2WindowClass)) { KWindowInfo info(window, 0, NET::WM2WindowClass); if (info.windowClassClass() != mGroupName) { onWindowRemoved(window); return false; } } // window changed virtual desktop if (prop.testFlag(NET::WMDesktop) || prop.testFlag(NET::WMGeometry)) { if (parentTaskBar()->isShowOnlyOneDesktopTasks() || parentTaskBar()->isShowOnlyCurrentScreenTasks()) { needsRefreshVisibility = true; } } // if (prop.testFlag(NET::WMVisibleName) || prop.testFlag(NET::WMName)) // std::for_each(buttons.begin(), buttons.end(), std::mem_fn(&UKUITaskButton::updateText)); // XXX: we are setting window icon geometry -> don't need to handle NET::WMIconGeometry // Icon of the button can be based on windowClass // if (prop.testFlag(NET::WMIcon) || prop2.testFlag(NET::WM2WindowClass)) // std::for_each(buttons.begin(), buttons.end(), std::mem_fn(&UKUITaskButton::updateIcon)); if (prop.testFlag(NET::WMIcon) || prop2.testFlag(NET::WM2WindowClass)){ updateIcon(); for(UKUITaskButtonHash::const_iterator i=mVisibleHash.begin();i!= mVisibleHash.end();i++) i.value()->updateIcon(); } if (prop.testFlag(NET::WMState)) { KWindowInfo info{window, NET::WMState}; if (info.hasState(NET::SkipTaskbar)) onWindowRemoved(window); // std::for_each(buttons.begin(), buttons.end(), std::bind(&UKUITaskButton::setUrgencyHint, std::placeholders::_1, info.hasState(NET::DemandsAttention))); if (parentTaskBar()->isShowOnlyMinimizedTasks()) { needsRefreshVisibility = true; } } } if (needsRefreshVisibility) refreshVisibility(); return true; } /************************************************ ************************************************/ void UKUITaskGroup::groupPopupShown(UKUITaskGroup * const sender) { //close all popups (should they be visible because of close delay) if (this != sender && isVisible()) setPopupVisible(false, true/*fast*/); } void UKUITaskGroup::removeWidget() { if(mpScrollArea) { removeSrollWidget(); } if(mpWidget) { mPopup->layout()->removeWidget(mpWidget); QHBoxLayout *hLayout = dynamic_cast(mpWidget->layout()); QVBoxLayout *vLayout = dynamic_cast(mpWidget->layout()); if(hLayout != NULL) { hLayout->deleteLater(); hLayout = NULL; } if(vLayout != NULL) { vLayout->deleteLater(); vLayout = NULL; } //mpWidget->setParent(NULL); mpWidget->deleteLater(); mpWidget = NULL; } } void UKUITaskGroup::removeSrollWidget() { if(mpScrollArea) { mPopup->layout()->removeWidget(mpScrollArea); mPopup->layout()->removeWidget(mpScrollArea->takeWidget()); } if(mpWidget) { mPopup->layout()->removeWidget(mpWidget); QHBoxLayout *hLayout = dynamic_cast(mpWidget->layout()); QVBoxLayout *vLayout = dynamic_cast(mpWidget->layout()); if(hLayout != NULL) { hLayout->deleteLater(); hLayout = NULL; } if(vLayout != NULL) { vLayout->deleteLater(); vLayout = NULL; } //mpWidget->setParent(NULL); mpWidget->deleteLater(); mpWidget = NULL; } if(mpScrollArea) { mpScrollArea->deleteLater(); mpScrollArea = NULL; } } void UKUITaskGroup::setLayOutForPostion() { if(mVisibleHash.size() > 10)//more than 10 need { mpWidget->setLayout(new QVBoxLayout); mpWidget->layout()->setAlignment(Qt::AlignTop); mpWidget->layout()->setSpacing(3); mpWidget->layout()->setMargin(3); return; } if(plugin()->panel()->isHorizontal()) { mpWidget->setLayout(new QHBoxLayout); mpWidget->layout()->setSpacing(3); mpWidget->layout()->setMargin(3); } else { mpWidget->setLayout(new QVBoxLayout); mpWidget->layout()->setSpacing(3); mpWidget->layout()->setMargin(3); } } bool UKUITaskGroup::isSetMaxWindow() { int iScreenWidth = QApplication::screens().at(0)->size().width(); int iScreenHeight = QApplication::screens().at(0)->size().height(); if((iScreenWidth >= SCREEN_MID_WIDTH_SIZE)||((iScreenWidth > SCREEN_MAX_WIDTH_SIZE) && (iScreenHeight > SCREEN_MAX_HEIGHT_SIZE))) { return true; } else { return false; } } void UKUITaskGroup::showPreview() { int n = 6; if (plugin()->panel()->isHorizontal()) n = 10; if(mVisibleHash.size() <= n) { showAllWindowByThumbnail(); } else { showAllWindowByList(); } } void UKUITaskGroup::adjustPopWindowSize(int winWidth, int winHeight) { int size = mVisibleHash.size(); if (isWaylandGroup) size = 1; if(plugin()->panel()->isHorizontal()) { mPopup->setFixedSize(winWidth*size + (size + 1)*3, winHeight + 6); } else { mPopup->setFixedSize(winWidth + 6,winHeight*size + (size + 1)*3); } mPopup->adjustSize(); } void UKUITaskGroup::v_adjustPopWindowSize(int winWidth, int winHeight, int v_all) { int fixed_size = v_all; if(plugin()->panel()->isHorizontal()) { int iScreenWidth = QApplication::screens().at(0)->size().width(); if (fixed_size > iScreenWidth) fixed_size = iScreenWidth; mPopup->setFixedSize(fixed_size, winHeight + 6); } else { int iScreenHeight = QApplication::screens().at(0)->size().height(); if (fixed_size > iScreenHeight) fixed_size = iScreenHeight; mPopup->setFixedSize(winWidth + 6, fixed_size); } mPopup->adjustSize(); } void UKUITaskGroup::timeout() { if(mTaskGroupEvent == ENTEREVENT) { if(mTimer->isActive()) { mTimer->stop(); } handleSavedEvent(); } else if(mTaskGroupEvent == LEAVEEVENT) { if(mTimer->isActive()) { mTimer->stop(); } setPopupVisible(false); QToolButton::leaveEvent(mEvent); taskgroupStatus = NORMAL; update(); } else { setPopupVisible(false); } } int UKUITaskGroup::calcAverageHeight() { if(plugin()->panel()->isHorizontal()) { return 0; } else { int size = mVisibleHash.size(); int iScreenHeight = QApplication::screens().at(0)->size().height(); int iMarginHeight = (size+1)*3; int iAverageHeight = (iScreenHeight - iMarginHeight)/size;//calculate average width of window return iAverageHeight; } } int UKUITaskGroup::calcAverageWidth() { if(plugin()->panel()->isHorizontal()) { int size = mVisibleHash.size(); int iScreenWidth = QApplication::screens().at(0)->size().width(); int iMarginWidth = (size+1)*3; int iAverageWidth; iAverageWidth = (size == 0 ? size : (iScreenWidth - iMarginWidth)/size);//calculate average width of window return iAverageWidth; } else { return 0; } } void UKUITaskGroup::showAllWindowByList() { int winWidth = 246; int winheight = 46; int iPreviewPosition = 0; int popWindowheight = (winheight) * (mVisibleHash.size()); int screenAvailabelHeight = QApplication::screens().at(0)->size().height() - plugin()->panel()->panelSize(); if(!plugin()->panel()->isHorizontal()) { screenAvailabelHeight = QApplication::screens().at(0)->size().height();//panel is vect } if(mPopup->layout()->count() > 0) { removeSrollWidget(); } mpScrollArea = new QScrollArea(this); mpScrollArea->setWidgetResizable(true); mPopup->layout()->addWidget(mpScrollArea); mPopup->setFixedSize(winWidth, popWindowheight < screenAvailabelHeight? popWindowheight : screenAvailabelHeight); mpWidget = new QWidget(this); mpScrollArea->setWidget(mpWidget); setLayOutForPostion(); /*begin catch preview picture*/ for (QVector::iterator it = mShowInTurn.begin();it != mShowInTurn.end();it++) { UKUITaskWidget *btn = *it; btn->clearMask(); btn->setTitleFixedWidth(mpWidget->width()); btn->updateTitle(); btn->setParent(mpScrollArea); btn->removeThumbNail(); btn->addThumbNail(); btn->adjustSize(); btn->setFixedHeight(winheight); connect(btn, &UKUITaskWidget::closeSigtoPop, [this] { mPopup->pubcloseWindowDelay(); }); connect(btn, &UKUITaskWidget::closeSigtoGroup, [this] { closeGroup(); }); mpWidget->layout()->addWidget(btn); } /*end*/ plugin()->willShowWindow(mPopup); if(plugin()->panel()->isHorizontal()) { iPreviewPosition = plugin()->panel()->panelSize()/2 - winWidth/2; mPopup->setGeometry(plugin()->panel()->calculatePopupWindowPos(mapToGlobal(QPoint(iPreviewPosition,0)), mPopup->size())); } else { iPreviewPosition = plugin()->panel()->panelSize()/2 - winWidth/2; mPopup->setGeometry(plugin()->panel()->calculatePopupWindowPos(mapToGlobal(QPoint(0,iPreviewPosition)), mPopup->size())); } mPopup->setStyle(new CustomStyle()); mpScrollArea->setAttribute(Qt::WA_TranslucentBackground); mpScrollArea->setProperty("drawScrollBarGroove",false); mpScrollArea->verticalScrollBar()->setProperty("drawScrollBarGroove",false); mpScrollArea->show(); mPopup->show(); // emit popupShown(this); } void UKUITaskGroup::showAllWindowByThumbnail() { if (isWaylandGroup) { int previewPosition = 0; mpWidget = new QWidget(); mpWidget->setAttribute(Qt::WA_TranslucentBackground); for (UKUITaskButtonHash::const_iterator it = mButtonHash.begin();it != mButtonHash.end();it++) { QPixmap thumbnail; UKUITaskWidget *btn = it.value(); thumbnail = QIcon::fromTheme(mIconName).pixmap(THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT - 160); btn->setThumbNail(thumbnail); btn->wl_updateTitle(mCaption); btn->wl_updateIcon(mIconName); btn->setFixedSize(THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT - 160); //mpWidget->layout()->setContentsMargins(0,0,0,0); //mpWidget->layout()->addWidget(btn); } adjustPopWindowSize(THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT - 160); if(plugin()->panel()->isHorizontal())//set preview window position { if(mPopup->size().width()/2 < QCursor::pos().x()) { previewPosition = 0 - mPopup->size().width()/2 + plugin()->panel()->panelSize()/2; } else { previewPosition = 0 -(QCursor::pos().x() + plugin()->panel()->panelSize()/2); } mPopup->setGeometry(plugin()->panel()->calculatePopupWindowPos(mapToGlobal(QPoint(previewPosition,0)), mPopup->size())); } else { if(mPopup->size().height()/2 < QCursor::pos().y()) { previewPosition = 0 - mPopup->size().height()/2 + plugin()->panel()->panelSize()/2; } else { previewPosition = 0 -(QCursor::pos().y() + plugin()->panel()->panelSize()/2); } mPopup->setGeometry(plugin()->panel()->calculatePopupWindowPos(mapToGlobal(QPoint(0,previewPosition)), mPopup->size())); } if(mPopup->isVisible()) { // mPopup- } else { mPopup->show(); } return; } XImage *img = NULL; Display *display = NULL; QPixmap thumbnail; XWindowAttributes attr; int previewPosition = 0; int winWidth = 0; int winHeight = 0; int truewidth = 0; // initVisibleHash(); refreshVisibility(); int iAverageWidth = calcAverageWidth(); int iAverageHeight = calcAverageHeight(); /*begin get the winsize*/ bool isMaxWinSize = isSetMaxWindow(); if(isMaxWinSize) { if(0 == iAverageWidth) { winHeight = PREVIEW_WIDGET_MAX_HEIGHT < iAverageHeight?PREVIEW_WIDGET_MAX_HEIGHT:iAverageHeight; winWidth = winHeight*PREVIEW_WIDGET_MAX_WIDTH/PREVIEW_WIDGET_MAX_HEIGHT; } else { winWidth = PREVIEW_WIDGET_MAX_WIDTH < iAverageWidth?PREVIEW_WIDGET_MAX_WIDTH:iAverageWidth; winHeight = winWidth*PREVIEW_WIDGET_MAX_HEIGHT/PREVIEW_WIDGET_MAX_WIDTH; } } else { if(0 == iAverageWidth) { winHeight = PREVIEW_WIDGET_MIN_HEIGHT < iAverageHeight?PREVIEW_WIDGET_MIN_HEIGHT:iAverageHeight; winWidth = winHeight*PREVIEW_WIDGET_MIN_WIDTH/PREVIEW_WIDGET_MIN_HEIGHT; } else { winWidth = PREVIEW_WIDGET_MIN_WIDTH < iAverageWidth?PREVIEW_WIDGET_MIN_WIDTH:iAverageWidth; winHeight = winWidth*PREVIEW_WIDGET_MIN_HEIGHT/PREVIEW_WIDGET_MIN_WIDTH; } } /*end get the winsize*/ if(mPopup->layout()->count() > 0) { removeWidget(); } mpWidget = new QWidget(this); mpWidget->setAttribute(Qt::WA_TranslucentBackground); setLayOutForPostion(); /*begin catch preview picture*/ int max_Height = 0; int max_Width = 0; int imgWidth_sum = 0; int changed = 0; int title_width = 0; int v_all = 0; int iScreenWidth = QApplication::screens().at(0)->size().width(); float minimumHeight = THUMBNAIL_HEIGHT; for (UKUITaskButtonHash::const_iterator it = mVisibleHash.begin();it != mVisibleHash.end();it++) { it.value()->removeThumbNail(); display = XOpenDisplay(nullptr); XGetWindowAttributes(display, it.key(), &attr); max_Height = attr.height > max_Height ? attr.height : max_Height; max_Width = attr.width > max_Width ? attr.width : max_Width; truewidth += attr.width; if(display) XCloseDisplay(display); } for (UKUITaskButtonHash::const_iterator it = mButtonHash.begin();it != mButtonHash.end();it++) { UKUITaskWidget *btn = it.value(); btn->setParent(mPopup); connect(btn, &UKUITaskWidget::closeSigtoPop, [this] { mPopup->pubcloseWindowDelay(); }); connect(btn, &UKUITaskWidget::closeSigtoGroup, [this] { closeGroup(); }); btn->addThumbNail(); display = XOpenDisplay(nullptr); XGetWindowAttributes(display, it.key(), &attr); img = XGetImage(display, it.key(), 0, 0, attr.width, attr.height, 0xffffffff,ZPixmap); float imgWidth = 0; float imgHeight = 0; if (plugin()->panel()->isHorizontal()) { float thmbwidth = (float)attr.width / (float)attr.height; imgWidth = thmbwidth * winHeight; imgHeight = winHeight; if (imgWidth > THUMBNAIL_WIDTH) imgWidth = THUMBNAIL_WIDTH; } else { imgWidth = THUMBNAIL_WIDTH; imgHeight = (float)attr.height / (float)attr.width * THUMBNAIL_WIDTH; } if (plugin()->panel()->isHorizontal()) { if (mVisibleHash.contains(btn->windowId())) { v_all += (int)imgWidth; imgWidth_sum += (int)imgWidth; } if (mVisibleHash.size() == 1 ) { changed = (int)imgWidth; } btn->setThumbMaximumSize(MAX_SIZE_OF_Thumb); btn->setThumbScale(true); } else { if (attr.width != max_Width) { float tmp = (float)attr.width / (float)max_Width; imgWidth = imgWidth * tmp; } if ((int)imgHeight > (int)minimumHeight) { imgHeight = minimumHeight; } if (mVisibleHash.contains(btn->windowId())) { v_all += (int)imgHeight; } if (mVisibleHash.size() == 1 ) changed = (int)imgHeight; if ((int)imgWidth < 150) { btn->setThumbFixedSize((int)imgWidth); btn->setThumbScale(false); } else { btn->setThumbMaximumSize(MAX_SIZE_OF_Thumb); btn->setThumbScale(true); } } if(img) { thumbnail = qimageFromXImage(img).scaled((int)imgWidth, (int)imgHeight, Qt::KeepAspectRatio,Qt::SmoothTransformation); if (!parentTaskBar()->getCpuInfoFlg()) thumbnail.save(QString("/tmp/%1.png").arg(it.key())); } else { qDebug()<<"can not catch picture"; QPixmap pxmp; if (pxmp.load(QString("/tmp/%1.png").arg(it.key()))) thumbnail = pxmp.scaled((int)imgWidth, (int)imgHeight, Qt::KeepAspectRatio,Qt::SmoothTransformation); else { thumbnail = QPixmap((int)imgWidth, (int)imgHeight); thumbnail.fill(QColor(0, 0, 0, 127)); } } btn->setThumbNail(thumbnail); btn->updateTitle(); btn->setFixedSize((int)imgWidth, (int)imgHeight); mpWidget->layout()->setContentsMargins(0,0,0,0); mpWidget->layout()->addWidget(btn); if(img) { XDestroyImage(img); } if(display) { XCloseDisplay(display); } } /*end*/ for (UKUITaskButtonHash::const_iterator it = mButtonHash.begin();it != mButtonHash.end();it++) { UKUITaskWidget *btn = it.value(); if (plugin()->panel()->isHorizontal()) { if (imgWidth_sum > iScreenWidth) title_width = (int)(btn->width() * iScreenWidth / imgWidth_sum - 80); else title_width = btn->width() - 75; } else { title_width = winWidth- 70; } btn->setTitleFixedWidth(title_width); } plugin()->willShowWindow(mPopup); mPopup->layout()->addWidget(mpWidget); if (mVisibleHash.size() == 1 && changed != 0) if (plugin()->panel()->isHorizontal()) { adjustPopWindowSize(changed, winHeight); } else { adjustPopWindowSize(winWidth, changed); } else if (mVisibleHash.size() != 1) v_adjustPopWindowSize(winWidth, winHeight, v_all); else adjustPopWindowSize(winWidth, winHeight); if(plugin()->panel()->isHorizontal())//set preview window position { if(mPopup->size().width()/2 < QCursor::pos().x()) { previewPosition = 0 - mPopup->size().width()/2 + plugin()->panel()->panelSize()/2; } else { previewPosition = 0 -(QCursor::pos().x() + plugin()->panel()->panelSize()/2); } mPopup->setGeometry(plugin()->panel()->calculatePopupWindowPos(mapToGlobal(QPoint(previewPosition,0)), mPopup->size())); } else { if(mPopup->size().height()/2 < QCursor::pos().y()) { previewPosition = 0 - mPopup->size().height()/2 + plugin()->panel()->panelSize()/2; } else { previewPosition = 0 -(QCursor::pos().y() + plugin()->panel()->panelSize()/2); } mPopup->setGeometry(plugin()->panel()->calculatePopupWindowPos(mapToGlobal(QPoint(0,previewPosition)), mPopup->size())); } if(mPopup->isVisible()) { // mPopup- } else { mPopup->show(); } // emit popupShown(this); } void UKUITaskGroup::setActivateState_wl(bool _state) { isWinActivate = _state; taskgroupStatus = (_state ? HOVER : NORMAL); repaint(); } void UKUITaskGroup::winClickActivate_wl(bool _getActive) { QDBusMessage message = QDBusMessage::createSignal("/", "com.ukui.kwin", "request"); QList args; quint32 m_wid=windowId(); args.append(m_wid); args.append((_getActive ? WAYLAND_GROUP_ACTIVATE : WAYLAND_GROUP_HIDE)); isWinActivate = _getActive; taskgroupStatus = (_getActive ? HOVER : NORMAL); repaint(); message.setArguments(args); QDBusConnection::sessionBus().send(message); } QWidget * UKUITaskGroup::wl_addWindow(WId id) { if (mButtonHash.contains(id)) return mButtonHash.value(id); UKUITaskWidget *btn; if (isWaylandGroup) { btn = new UKUITaskWidget(QString("kyiln-video"), id, parentTaskBar(), mPopup); mButtonHash.insert(id, btn); return btn; } else btn = new UKUITaskWidget(id, parentTaskBar(), mPopup); mButtonHash.insert(id, btn); connect(btn, SIGNAL(clicked()), this, SLOT(onClicked(bool))); connect(btn, SIGNAL(windowMaximize()), this, SLOT(onChildButtonClicked())); this->setStyle(new CustomStyle("taskbutton",true)); return btn; } void UKUITaskGroup::closeGroup_wl() { QDBusMessage message = QDBusMessage::createSignal("/", "com.ukui.kwin", "request"); QList args; quint32 m_wid=windowId(); args.append(m_wid); args.append(WAYLAND_GROUP_CLOSE); message.setArguments(args); QDBusConnection::sessionBus().send(message); } void UKUITaskGroup::wl_widgetUpdateTitle(QString caption) { if (caption.isNull()) return; for (UKUITaskWidget *button : qAsConst(mButtonHash) ) button->wl_updateTitle(caption); } ukui-panel-3.0.6.4/plugin-taskbar/translation/0000755000175000017500000000000014203402514017630 5ustar fengfengukui-panel-3.0.6.4/plugin-taskbar/translation/taskbar_zh_CN.ts0000644000175000017500000001437714203402514022724 0ustar fengfeng UKUITaskBar Drop Error File/URL '%1' cannot be embedded into QuickLaunch for now UKUITaskButton Application To &Desktop &All Desktops Desktop &%1 &To Current Desktop &Move Resi&ze Ma&ximize Maximize vertically Maximize horizontally &Restore Mi&nimize Roll down Roll up &Layer Always on &top &Normal Always on &bottom &Close delete from quicklaunch 从任务栏取消固定 UKUITaskGroup Group delete from taskbar 从任务栏取消固定 add to taskbar 添加到任务栏 close 关闭 UKUITaskWidget Widget close 关闭 restore 恢复 maximaze 最大化 minimize 最小化 above 置顶 clear 取消置顶 ukui-panel-3.0.6.4/plugin-taskbar/ukuitaskbar.cpp0000644000175000017500000012354514203402514020335 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2011 Razor team * 2014 LXQt team * Authors: * Alexander Sokoloff * Maciej Płaza * Kuzma Shapran * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../panel/common/ukuigridlayout.h" #include "ukuitaskbar.h" #include "ukuitaskgroup.h" #include "quicklaunchaction.h" #define PANEL_SETTINGS "org.ukui.panel.settings" #define PANEL_LINES "panellines" #define PANEL_CONFIG_PATH "/usr/share/ukui/ukui-panel/panel-commission.ini" #define PANEL_POSITION_KEY "panelposition" using namespace UKUi; /************************************************ ************************************************/ UKUITaskBar::UKUITaskBar(IUKUIPanelPlugin *plugin, QWidget *parent) : QScrollArea(parent), mSignalMapper(new QSignalMapper(this)), mButtonStyle(Qt::ToolButtonIconOnly), mButtonWidth(400), mButtonHeight(100), mCloseOnMiddleClick(true), mRaiseOnCurrentDesktop(true), mShowOnlyOneDesktopTasks(true), mShowDesktopNum(0), mShowOnlyCurrentScreenTasks(false), mShowOnlyMinimizedTasks(false), mAutoRotate(true), mGroupingEnabled(true), mShowGroupOnHover(true), mIconByClass(false), mCycleOnWheelScroll(true), mPlugin(plugin), mIgnoreWindow(), mPlaceHolder(new QWidget(this)), mStyle(new LeftAlignedTextStyle()) { mAllFrame=new QWidget(this); mAllFrame->setAttribute(Qt::WA_TranslucentBackground); this->setWidget(mAllFrame); this->horizontalScrollBar()->setVisible(false); this->verticalScrollBar()->setVisible(false); this->setFrameShape(QFrame::NoFrame);//去掉边框 this->setWidgetResizable(true); //临时方案解决任务栏出现滚动时有滑动条区域遮挡图标,待滚动提示样式确认后再进行替换 horizontalScrollBar()->setStyleSheet("QScrollBar {height:0px;}"); verticalScrollBar()->setStyleSheet("QScrollBar {width:0px;}"); QPalette pal = this->palette(); pal.setBrush(QPalette::Window, QColor(Qt::transparent)); this->setPalette(pal); taskstatus=NORMAL; mLayout = new UKUi::GridLayout(mAllFrame); mAllFrame->setLayout(mLayout); mLayout->setMargin(0); mLayout->setStretch(UKUi::GridLayout::StretchHorizontal | UKUi::GridLayout::StretchVertical); mPlaceHolder->setMinimumSize(1,1); mPlaceHolder->setMaximumSize(QWIDGETSIZE_MAX,QWIDGETSIZE_MAX); mPlaceHolder->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding)); QString filename = QString::fromLocal8Bit(PANEL_CONFIG_PATH); QSettings m_settings(filename, QSettings::IniFormat); m_settings.setIniCodec("UTF-8"); m_settings.beginGroup("IgnoreWindow"); mIgnoreWindow = m_settings.value("ignoreWindow", "").toStringList(); m_settings.endGroup(); //往任务栏中加入快速启动按钮 refreshQuickLaunch(); realign(); settingsChanged(); setAcceptDrops(true); const QByteArray id(PANEL_SETTINGS); if (QGSettings::isSchemaInstalled(id)) { settings=new QGSettings(id); } mAndroidIconHash=matchAndroidIcon(); const QByteArray id_Theme("org.ukui.style"); if(QGSettings::isSchemaInstalled(id_Theme)){ changeTheme = new QGSettings(id_Theme); } connect(changeTheme, &QGSettings::changed, this, [=] (const QString &key){ if(key=="iconThemeName"){ sleep(1); for(auto it= mKnownWindows.begin(); it != mKnownWindows.end();it++) { UKUITaskGroup *group = it.value(); group->updateIcon(); } } if(key == PANEL_POSITION_KEY) { realign(); } }); connect(mSignalMapper, static_cast(&QSignalMapper::mapped), this, &UKUITaskBar::activateTask); connect(KWindowSystem::self(), static_cast(&KWindowSystem::windowChanged) , this, &UKUITaskBar::onWindowChanged); connect(KWindowSystem::self(), &KWindowSystem::windowAdded, this, &UKUITaskBar::onWindowAdded); connect(KWindowSystem::self(), &KWindowSystem::windowRemoved, this, &UKUITaskBar::onWindowRemoved); connect(KWindowSystem::self(), SIGNAL(currentDesktopChanged(int)), this, SLOT(onDesktopChanged())); saveSettings(); /**/ QDBusConnection::sessionBus().unregisterService("com.ukui.panel.plugins.service"); QDBusConnection::sessionBus().registerService("com.ukui.panel.plugins.service"); QDBusConnection::sessionBus().registerObject("/taskbar/click", this,QDBusConnection :: ExportAllSlots | QDBusConnection :: ExportAllSignals); QDBusConnection::sessionBus().connect(QString(), QString("/taskbar/quicklaunch"), "org.ukui.panel.taskbar", "AddToTaskbar", this, SLOT(_AddToTaskbar(QString))); QDBusConnection::sessionBus().connect(QString(), QString("/taskbar/quicklaunch"), "org.ukui.panel.taskbar", "RemoveFromTaskbar", this, SLOT(removeFromTaskbar(QString))); if (mLayout->count() == 0) { mLayout->addWidget(mPlaceHolder); } else { mPlaceHolder->setFixedSize(0,0); } QDBusConnection::sessionBus().connect(QString(), QString("/"), "com.ukui.panel", "event", this, SLOT(wl_kwinSigHandler(quint32,int, QString, QString))); } /************************************************ ************************************************/ UKUITaskBar::~UKUITaskBar() { for(auto it = mVBtn.begin(); it != mVBtn.end();) { (*it)->deleteLater(); mVBtn.erase(it); } mVBtn.clear(); } QString UKUITaskBar::readFile(const QString &filename) { QFile f(filename); if (!f.open(QFile::ReadOnly)) { return QString(); } else { QTextStream in(&f); return in.readAll(); } } bool UKUITaskBar::isFileExit(const QString &filename) { QFile f(filename); return f.exists(); } void UKUITaskBar::onDesktopChanged() { for (auto i = mKnownWindows.begin(); mKnownWindows.end() != i; ++i) { (*i)->onDesktopChanged(); if ((*i)->existSameQckBtn) { UKUITaskGroup* btn = (*i)->getOwnQckBtn(); if (mVBtn.contains(btn)) btn->setVisible((*i)->isHidden()); } } } void UKUITaskBar::refreshQuickLaunch(){ for(auto it = mVBtn.begin(); it != mVBtn.end();) { (*it)->deleteLater(); mVBtn.erase(it); } QString desktop; QString file; //gsetting的方式读取写入 apps QList > apps = mPlugin->settings()->readArray("apps"); QString filename = QDir::homePath() + "/.config/ukui/panel.conf"; QSettings user_qsettings(filename,QSettings::IniFormat); QStringList groupname = user_qsettings.childGroups(); //为了兼容3.0版本和3.1版本,后续版本考虑删除 if (apps.isEmpty() && groupname.contains("quicklaunch")) { apps = copyQuicklaunchConfig(); } else if (groupname.contains("quicklaunch")) { user_qsettings.remove("quicklaunch"); } for (const QMap &app : apps) { desktop = app.value("desktop", "").toString(); qDebug()<<"desktop ******"< > UKUITaskBar::copyQuicklaunchConfig() { QString filename = QDir::homePath() + "/.config/ukui/panel.conf"; //若taskbar中没有apps,则把quicklaunch中的内容复制到taskbar qDebug()<<"Taskbar is empty, read apps from quicklaunch"; QSettings user_qsettings(filename,QSettings::IniFormat); user_qsettings.beginGroup("quicklaunch"); QList > array; int size = user_qsettings.beginReadArray("apps"); for (int i = 0; i < size; ++i) { user_qsettings.setArrayIndex(i); QMap map; map["desktop"] = user_qsettings.value("desktop"); if (array.contains(map)) { continue; } else { array << map; } } user_qsettings.endArray(); user_qsettings.endGroup(); user_qsettings.remove("quicklaunch"); user_qsettings.sync(); return array; } bool UKUITaskBar::acceptWindow(WId window) const { QFlags ignoreList; ignoreList |= NET::DesktopMask; ignoreList |= NET::DockMask; ignoreList |= NET::SplashMask; ignoreList |= NET::ToolbarMask; ignoreList |= NET::MenuMask; ignoreList |= NET::PopupMenuMask; ignoreList |= NET::NotificationMask; KWindowInfo info(window, NET::WMWindowType | NET::WMState, NET::WM2TransientFor); if (!info.valid()) return false; if (NET::typeMatchesMask(info.windowType(NET::AllTypesMask), ignoreList)) return false; if (info.state() & NET::SkipTaskbar) return false; // WM_TRANSIENT_FOR hint not set - normal window WId transFor = info.transientFor(); if (transFor == 0 || transFor == window || transFor == (WId) QX11Info::appRootWindow()) return true; info = KWindowInfo(transFor, NET::WMWindowType); QFlags normalFlag; normalFlag |= NET::NormalMask; normalFlag |= NET::DialogMask; normalFlag |= NET::UtilityMask; return !NET::typeMatchesMask(info.windowType(NET::AllTypesMask), normalFlag); } void UKUITaskBar::dragEnterEvent(QDragEnterEvent* event) { } void UKUITaskBar::dragMoveEvent(QDragMoveEvent * event) { } void UKUITaskBar::dropEvent(QDropEvent *e) { } void UKUITaskBar::buttonMove(UKUITaskGroup * dst, UKUITaskGroup * src, QPoint const & pos) { int src_index; if (!src || -1 == (src_index = mLayout->indexOf(src))) { return; } const int size = mLayout->count(); Q_ASSERT(0 < size); //dst is nullptr in case the drop occured on empty space in taskbar int dst_index; if (nullptr == dst) { //moving based on taskbar (not signaled by button) QRect occupied = mLayout->occupiedGeometry(); QRect last_empty_row{occupied}; const QRect last_item_geometry = mLayout->itemAt(size - 1)->geometry(); if (mPlugin->panel()->isHorizontal()) { if (isRightToLeft()) { last_empty_row.setTopRight(last_item_geometry.topLeft()); } else { last_empty_row.setTopLeft(last_item_geometry.topRight()); } } else { if (isRightToLeft()) { last_empty_row.setTopRight(last_item_geometry.topRight()); } else { last_empty_row.setTopLeft(last_item_geometry.topLeft()); } } if (occupied.contains(pos) && !last_empty_row.contains(pos)) { return; } dst_index = size; } else { //moving based on signal from child button dst_index = mLayout->indexOf(dst); } //moving lower index to higher one => consider as the QList::move => insert(to, takeAt(from)) if (src_index < dst_index) { if (size == dst_index || src_index + 1 != dst_index) { --dst_index; } else { //switching positions of next standing const int tmp_index = src_index; src_index = dst_index; dst_index = tmp_index; } } if (dst_index == src_index || mLayout->animatedMoveInProgress() ) { return; } mLayout->moveItem(src_index, dst_index, true); } void UKUITaskBar::groupBecomeEmptySlot() { //group now contains no buttons - clean up in hash and delete the group UKUITaskGroup * const group = qobject_cast(sender()); Q_ASSERT(group); for (auto i = mKnownWindows.begin(); mKnownWindows.end() != i; ) { if (group == *i) { swid.removeOne(i.key()); i = mKnownWindows.erase(i); break; } else ++i; } for (auto it = mVBtn.begin(); it!=mVBtn.end(); ++it) { UKUITaskGroup *pQuickBtn = *it; if(pQuickBtn->file_name == group->file_name &&(mLayout->indexOf(pQuickBtn) >= 0 )) { pQuickBtn->setHidden(false); mLayout->moveItem(mLayout->indexOf(pQuickBtn), mLayout->indexOf(group)); pQuickBtn->existSameQckBtn = false; break; } } mLayout->removeWidget(group); group->deleteLater(); } void UKUITaskBar::addWindow(WId window) { // If grouping disabled group behaves like regular button const QString group_id = mGroupingEnabled ? KWindowInfo(window, 0, NET::WM2WindowClass).windowClassClass() : QString("%1").arg(window); if (mIgnoreWindow.contains(group_id)) { return; } UKUITaskGroup *group = nullptr; bool isNeedAddNewWidget = true; auto i_group = mKnownWindows.find(window); if (mKnownWindows.end() != i_group) { if ((*i_group)->groupName() == group_id) group = *i_group; else (*i_group)->onWindowRemoved(window); } /*check if window belongs to some existing group * 安卓兼容应用的组名为kydroid-display-window * 需要将安卓兼容目录的分组特性关闭 */ QStringList andriod_window_list; andriod_window_list<<"kydroid-display-window"<<"kylin-kmre-window"<<""; if (!group && mGroupingEnabled && !andriod_window_list.contains(group_id)) { for (auto i = mKnownWindows.cbegin(), i_e = mKnownWindows.cend(); i != i_e; ++i) { if ((*i)->groupName() == group_id) { group = *i; break; } } } if (!group) { group = new UKUITaskGroup(group_id, window, this); connect(group, SIGNAL(groupBecomeEmpty(QString)), this, SLOT(groupBecomeEmptySlot())); connect(group, SIGNAL(t_saveSettings()), this, SLOT(saveSettingsSlot())); connect(group, SIGNAL(WindowAddtoTaskBar(QString)), this, SLOT(WindowAddtoTaskBar(QString))); connect(group, SIGNAL(WindowRemovefromTaskBar(QString)), this, SLOT(WindowRemovefromTaskBar(QString))); connect(group, SIGNAL(visibilityChanged(bool)), this, SLOT(refreshPlaceholderVisibility())); connect(group, &UKUITaskGroup::popupShown, this, &UKUITaskBar::popupShown); connect(group, &UKUITaskButton::dragging, this, [this] (QObject * dragSource, QPoint const & pos) { switchButtons(qobject_cast(sender()), qobject_cast(dragSource));//, pos); }); for (auto it = mVBtn.begin(); it!=mVBtn.end(); ++it) { UKUITaskGroup *pQuickBtn = *it; if(pQuickBtn->file_name == group->file_name &&(mLayout->indexOf(pQuickBtn) >= 0 )) { mLayout->addWidget(group); mLayout->moveItem(mLayout->indexOf(group), mLayout->indexOf(pQuickBtn)); pQuickBtn->setHidden(true); isNeedAddNewWidget = false; group->existSameQckBtn = true; pQuickBtn->existSameQckBtn = true; group->setQckLchBtn(pQuickBtn); break; } } if(isNeedAddNewWidget) { mLayout->addWidget(group); } group->setToolButtonsStyle(mButtonStyle); } mKnownWindows[window] = group; swid.push_back(window); group->addWindow(window); group->groupName(); group->updateIcon(); } auto UKUITaskBar::removeWindow(windowMap_t::iterator pos) -> windowMap_t::iterator { WId const window = pos.key(); UKUITaskGroup * const group = *pos; swid.removeOne(window); auto ret = mKnownWindows.erase(pos); group->onWindowRemoved(window); //if (countOfButtons() <= 32) tmpwidget->setHidden(true); return ret; } void UKUITaskBar::refreshTaskList() { QList new_list; // Just add new windows to groups, deleting is up to the groups const auto wnds = KWindowSystem::stackingOrder(); for (auto const wnd: wnds) { if (acceptWindow(wnd)) { new_list << wnd; addWindow(wnd); } } // mLayout->addWidget(tmpwidget); //emulate windowRemoved if known window not reported by KWindowSystem for (auto i = mKnownWindows.begin(), i_e = mKnownWindows.end(); i != i_e; ) { if (0 > new_list.indexOf(i.key())) { i = removeWindow(i); } else ++i; } refreshPlaceholderVisibility(); } void UKUITaskBar::onWindowChanged(WId window, NET::Properties prop, NET::Properties2 prop2) { auto i = mKnownWindows.find(window); if (mKnownWindows.end() != i) { if (!(*i)->onWindowChanged(window, prop, prop2) && acceptWindow(window)) { // window is removed from a group because of class change, so we should add it again addWindow(window); } } } void UKUITaskBar::onWindowAdded(WId window) { qDebug()<<"window is : ******"<panel()->position(); // emit buttonRotationRefreshed(autoRotate, panelPosition); } /************************************************ ************************************************/ void UKUITaskBar::refreshPlaceholderVisibility() { bool haveVisibleWindow = false; for (auto i = mKnownWindows.cbegin(), i_e = mKnownWindows.cend(); i_e != i; ++i) { if ((*i)->isVisible()) { haveVisibleWindow = true; break; } } mPlaceHolder->setVisible(!haveVisibleWindow); if (haveVisibleWindow || mLayout->count() != 0) { mPlaceHolder->setFixedSize(0,0); } else { mPlaceHolder->setMinimumSize(1,1); mPlaceHolder->setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); } } /************************************************ ************************************************/ void UKUITaskBar::setButtonStyle(Qt::ToolButtonStyle buttonStyle) { emit buttonStyleRefreshed(mButtonStyle); } void UKUITaskBar::settingsChanged() { bool groupingEnabledOld = mGroupingEnabled; bool showOnlyOneDesktopTasksOld = mShowOnlyOneDesktopTasks; const int showDesktopNumOld = mShowDesktopNum; bool showOnlyCurrentScreenTasksOld = mShowOnlyCurrentScreenTasks; bool showOnlyMinimizedTasksOld = mShowOnlyMinimizedTasks; const bool iconByClassOld = mIconByClass; mButtonWidth = mPlugin->settings()->value("buttonWidth", 400).toInt(); mButtonHeight = mPlugin->settings()->value("buttonHeight", 100).toInt(); QString s = mPlugin->settings()->value("buttonStyle").toString().toUpper(); if (s == "ICON") setButtonStyle(Qt::ToolButtonIconOnly); else if (s == "TEXT") setButtonStyle(Qt::ToolButtonTextOnly); else setButtonStyle(Qt::ToolButtonIconOnly); mShowOnlyOneDesktopTasks = mPlugin->settings()->value("showOnlyOneDesktopTasks", mShowOnlyOneDesktopTasks).toBool(); mShowDesktopNum = mPlugin->settings()->value("showDesktopNum", mShowDesktopNum).toInt(); mShowOnlyCurrentScreenTasks = mPlugin->settings()->value("showOnlyCurrentScreenTasks", mShowOnlyCurrentScreenTasks).toBool(); mShowOnlyMinimizedTasks = mPlugin->settings()->value("showOnlyMinimizedTasks", mShowOnlyMinimizedTasks).toBool(); mAutoRotate = mPlugin->settings()->value("autoRotate", true).toBool(); mCloseOnMiddleClick = mPlugin->settings()->value("closeOnMiddleClick", true).toBool(); mRaiseOnCurrentDesktop = mPlugin->settings()->value("raiseOnCurrentDesktop", false).toBool(); mGroupingEnabled = mPlugin->settings()->value("groupingEnabled",true).toBool(); mShowGroupOnHover = mPlugin->settings()->value("showGroupOnHover",true).toBool(); mIconByClass = mPlugin->settings()->value("iconByClass", false).toBool(); mCycleOnWheelScroll = mPlugin->settings()->value("cycleOnWheelScroll", true).toBool(); // Delete all groups if grouping feature toggled and start over if (groupingEnabledOld != mGroupingEnabled) { for (int i = mKnownWindows.size() - 1; 0 <= i; --i) { UKUITaskGroup * group = mKnownWindows.value(swid.value(i)); if (nullptr != group) { mLayout->takeAt(i); group->deleteLater(); } } mKnownWindows.clear(); swid.clear(); } if (showOnlyOneDesktopTasksOld != mShowOnlyOneDesktopTasks || (mShowOnlyOneDesktopTasks && showDesktopNumOld != mShowDesktopNum) || showOnlyCurrentScreenTasksOld != mShowOnlyCurrentScreenTasks || showOnlyMinimizedTasksOld != mShowOnlyMinimizedTasks ) emit showOnlySettingChanged(); if (iconByClassOld != mIconByClass) emit iconByClassChanged(); refreshTaskList(); } void UKUITaskBar::setShowGroupOnHover(bool bFlag) { mShowGroupOnHover = bFlag; } int i = 0; void UKUITaskBar::realign() { mLayout->setEnabled(false); refreshButtonRotation(); IUKUIPanel *panel = mPlugin->panel(); QSize maxSize = QSize(mPlugin->panel()->panelSize(), mPlugin->panel()->panelSize()); QSize minSize = QSize(mPlugin->panel()->iconSize()/2, mPlugin->panel()->iconSize()/2); int iconsize = panel->iconSize(); bool rotated = false; if (panel->isHorizontal()) { this->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); this->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); mAllFrame->setMinimumSize(QSize((mLayout->count()+5)*panel->panelSize(),panel->panelSize())); if (mAllFrame->width() < this->width()) { mAllFrame->setFixedWidth(this->width()); } mLayout->setRowCount(panel->lineCount()); mLayout->setColumnCount(0); } else { this->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); this->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); mAllFrame->setMinimumSize(QSize(panel->panelSize(),(mLayout->count()+3)*panel->panelSize())); if (mAllFrame->height() < this->height()) { mAllFrame->setFixedHeight(this->height()); } mLayout->setRowCount(0); if (mButtonStyle == Qt::ToolButtonIconOnly) { // Vertical + Icons mLayout->setColumnCount(panel->lineCount()); } else { rotated = mAutoRotate && (panel->position() == IUKUIPanel::PositionLeft || panel->position() == IUKUIPanel::PositionRight); // Vertical + Text if (rotated) { maxSize.rwidth() = mButtonHeight; maxSize.rheight() = mButtonWidth; mLayout->setColumnCount(panel->lineCount()); } else { mLayout->setColumnCount(1); } } } for(auto it= mKnownWindows.begin(); it != mKnownWindows.end();it++) { UKUITaskGroup *group = it.value(); group->setIconSize(QSize(iconsize,iconsize)); } for (int i = 0; i < mVBtn.size(); i++) { UKUITaskGroup * quicklaunch = mVBtn.value(i); quicklaunch->setIconSize(QSize(iconsize, iconsize)); } mLayout->setCellMinimumSize(minSize); mLayout->setCellMaximumSize(maxSize); mLayout->setDirection(rotated ? UKUi::GridLayout::TopToBottom : UKUi::GridLayout::LeftToRight); mLayout->setEnabled(true); //our placement on screen could have been changed emit showOnlySettingChanged(); emit refreshIconGeometry(); horizontalScrollBar()->setMaximum(mAllFrame->width() - this->width()); verticalScrollBar()->setMaximum(mAllFrame->height() - this->height()); } void UKUITaskBar::wheelEvent(QWheelEvent* event) { if (this->verticalScrollBarPolicy()==Qt::ScrollBarAlwaysOff) { if (event->delta()>=0) { horizontalScrollBar()->setValue(horizontalScrollBar()->value()-40); qDebug()<<"-40-horizontalScrollBar()->value()"<value(); } else { horizontalScrollBar()->setValue(horizontalScrollBar()->value()+40); if (horizontalScrollBar()->value()>mAllFrame->width()) { horizontalScrollBar()->setValue(mAllFrame->width()); } qDebug()<<"+40+horizontalScrollBar()->value()"<value(); } } else { if (event->delta()>=0) { verticalScrollBar()->setValue(verticalScrollBar()->value()-40); } else { verticalScrollBar()->setValue(verticalScrollBar()->value()+40); } } } void UKUITaskBar::resizeEvent(QResizeEvent* event) { emit refreshIconGeometry(); return QWidget::resizeEvent(event); } void UKUITaskBar::changeEvent(QEvent* event) { // if current style is changed, reset the base style of the proxy style // so we can apply the new style correctly to task buttons. if(event->type() == QEvent::StyleChange) mStyle->setBaseStyle(NULL); QFrame::changeEvent(event); } void UKUITaskBar::activateTask(int pos) { for (int i = 0; i < mKnownWindows.size(); ++i) { UKUITaskGroup * g = mKnownWindows.value(swid.value(i)); if (g && g->isVisible()) { pos--; if (pos == 0) { g->raiseApplication(); break; } } } } void UKUITaskBar::enterEvent(QEvent *) { taskstatus=HOVER; update(); } void UKUITaskBar::leaveEvent(QEvent *) { taskstatus=NORMAL; update(); } void UKUITaskBar::paintEvent(QPaintEvent *) { QStyleOption opt; opt.initFrom(this); QPainter p(this); p.setRenderHint(QPainter::Antialiasing); QPainterPath rectPath; rectPath.addRoundedRect(this->rect(),6,6); // 画一个黑底 QPixmap pixmap(this->rect().size()); pixmap.fill(Qt::transparent); QPainter pixmapPainter(&pixmap); pixmapPainter.setRenderHint(QPainter::Antialiasing); pixmapPainter.drawPath(rectPath); pixmapPainter.end(); // 模糊这个黑底 extern void qt_blurImage(QImage &blurImage, qreal radius, bool quality, int transposed); QImage img = pixmap.toImage(); qt_blurImage(img, 10, false, false); switch(taskstatus) { case NORMAL: { p.setPen(Qt::NoPen); break; } case HOVER: { p.setPen(Qt::NoPen); break; } case PRESS: { p.setPen(Qt::NoPen); break; } } QPalette pal = this->palette(); pal.setBrush(QPalette::Base, QColor(0,0,0,0)); //背景透明 this->viewport()->setPalette(pal); this->setPalette(pal); mAllFrame->setPalette(pal); p.setRenderHint(QPainter::Antialiasing); p.drawRoundedRect(opt.rect,6,6); style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); } void UKUITaskBar::mouseMoveEvent(QMouseEvent *e) { QFrame::mouseMoveEvent(e); } void UKUITaskBar::mousePressEvent(QMouseEvent *) { QDBusMessage message =QDBusMessage::createSignal("/taskbar/click", "com.ukui.panel.plugins.taskbar", "sendToUkuiDEApp"); QDBusConnection::sessionBus().send(message); } /////////////////////////////////////////// //////////////////////////////////////////////////////////////////// /// About Quick Launch Functions /// /// void UKUITaskBar::addButton(QuickLaunchAction* action) { bool isNeedAddNewWidget = true; mLayout->setEnabled(false); UKUITaskGroup *btn = new UKUITaskGroup(action, mPlugin, this); btn->setArrowType(Qt::NoArrow); /*@bug * 快速启动栏右键菜单原本的样式有对于不可选项有置灰效果, * 后跟随主题框架之后置灰效果消失,可能与此属性相关 */ // btn->setMenu(Qt::InstantPopup); for (auto it = mKnownWindows.begin(); it!=mKnownWindows.end(); ++it) { UKUITaskGroup *group = *it; if(btn->file_name == group->file_name &&(mLayout->indexOf(group) >= 0)) { mLayout->addWidget(btn); mLayout->moveItem(mLayout->indexOf(btn), mLayout->indexOf(group)); isNeedAddNewWidget = false; group->existSameQckBtn = true; btn->existSameQckBtn = true; mVBtn.push_back(btn); group->setQckLchBtn(btn); btn->setHidden(group->isVisible()); break; } } if (isNeedAddNewWidget) { mLayout->addWidget(btn); btn->setIconSize(QSize(mPlugin->panel()->iconSize(),mPlugin->panel()->iconSize())); mVBtn.push_back(btn); mLayout->moveItem(mLayout->indexOf(btn), countOfButtons() - 1); } connect(btn, &UKUITaskButton::dragging, this, [this] (QObject * dragSource, QPoint const & pos) { switchButtons(qobject_cast(sender()), qobject_cast(dragSource));//, pos); }); connect(btn, SIGNAL(buttonDeleted()), this, SLOT(buttonDeleted())); connect(btn, SIGNAL(t_saveSettings()), this, SLOT(saveSettingsSlot())); mLayout->setEnabled(true); } void UKUITaskBar::switchButtons(UKUITaskGroup *dst_button, UKUITaskGroup *src_button) { if (dst_button == src_button) return; if (!dst_button || !src_button) return; int dst = mLayout->indexOf(dst_button); int src = mLayout->indexOf(src_button); if (dst == src || mLayout->animatedMoveInProgress() ) { return; } mLayout->moveItem(src, dst, true); saveSettings(); } bool UKUITaskBar::checkButton(QuickLaunchAction* action) { bool checkresult; UKUITaskGroup* btn = new UKUITaskGroup(action, mPlugin, this); int i = 0; int counts = mVBtn.size(); if(mVBtn.size()>0){ while (i != counts) { UKUITaskGroup *b = mVBtn.value(i); qDebug()<<"mLayout->itemAt("<file_name == btn->file_name) { checkresult=true; break; } else { checkresult=false; ++i; } } delete btn; return checkresult; } else{ qDebug()<<"countOfButtons = "<file_name, tmp->file_name) == 0) { doInitGroupButton(tmp->file_name); tmp->deleteLater(); mLayout->removeWidget(tmp); mVBtn.remove(i); break; } ++i; } btn->deleteLater(); saveSettings(); } void UKUITaskBar::removeButton(QString file) { int i = 0; while (i < mVBtn.size()) { UKUITaskGroup *tmp = mVBtn.value(i); if (QString::compare(file, tmp->file_name) == 0) { doInitGroupButton(tmp->file_name); tmp->deleteLater(); mLayout->removeWidget(tmp); mVBtn.remove(i); break; } ++i; } } void UKUITaskBar::WindowAddtoTaskBar(QString arg) { for(auto it= mKnownWindows.begin(); it != mKnownWindows.end();it++) { UKUITaskGroup *group = it.value(); if (arg.compare(group->groupName()) == 0) { _AddToTaskbar(group->file_name); break; } } } void UKUITaskBar::WindowRemovefromTaskBar(QString arg) { for (auto it = mVBtn.begin(); it!=mVBtn.end(); ++it) { UKUITaskGroup *pQuickBtn = *it; if(pQuickBtn->file_name == arg && (mLayout->indexOf(pQuickBtn) >= 0 )) { doInitGroupButton(pQuickBtn->file_name); mVBtn.removeOne(pQuickBtn); pQuickBtn->deleteLater(); mLayout->removeWidget(pQuickBtn); saveSettings(); break; } } } void UKUITaskBar::_AddToTaskbar(QString arg) { const auto url=QUrl(arg); QString fileName(url.isLocalFile() ? url.toLocalFile() : url.url()); QFileInfo fi(fileName); XdgDesktopFile xdg; if (xdg.load(fileName)){ if(!checkButton(new QuickLaunchAction(&xdg, this))){ addButton(new QuickLaunchAction(&xdg, this)); mPlaceHolder->hide(); } }else{ qWarning() << "XdgDesktopFile" << fileName << "is not valid"; QMessageBox::information(this, tr("Drop Error"), tr("File/URL '%1' cannot be embedded into QuickLaunch for now").arg(fileName) ); } saveSettings(); } void UKUITaskBar::removeFromTaskbar(QString arg) { XdgDesktopFile xdg; xdg.load(arg); removeButton(new QuickLaunchAction(&xdg, this)); } void UKUITaskBar::doInitGroupButton(QString sname) { for(auto it= mKnownWindows.begin(); it != mKnownWindows.end();it++) { UKUITaskGroup *group = it.value(); if (group->existSameQckBtn) { if (sname == group->file_name) { group->existSameQckBtn = false; group->setQckLchBtn(NULL); break; } } } } void UKUITaskBar::buttonDeleted() { UKUITaskGroup *btn = qobject_cast(sender()); if (!btn) return; for(auto it = mVBtn.begin();it != mVBtn.end();it++) { if(*it == btn) { for(auto it= mKnownWindows.begin(); it != mKnownWindows.end();it++) { UKUITaskGroup *group = it.value(); if (group->existSameQckBtn) { if (btn->file_name == group->file_name) { group->existSameQckBtn = false; group->setQckLchBtn(NULL); } } } mVBtn.erase(it); break; } } mLayout->removeWidget(btn); btn->deleteLater(); saveSettings(); } void UKUITaskBar::saveSettingsSlot() { saveSettings(); } void UKUITaskBar::saveSettings() { PluginSettings *settings = mPlugin->settings(); settings->remove("apps"); QList > hashList; int size = mLayout->count(); for (int j = 0; j < size; ++j) { UKUITaskGroup *b = qobject_cast(mLayout->itemAt(j)->widget()); if (!(mVBtn.contains(b) || mKnownWindows.contains(mKnownWindows.key(b)))) continue; if (!b->statFlag && b->existSameQckBtn) continue; if (!b) continue; if (b->statFlag && b->existSameQckBtn){ b = b->getQckLchBtn(); } if (!b || b->statFlag) continue; // convert QHash to QMap QMap map; QHashIterator it(b->settingsMap()); while (it.hasNext()) { it.next(); map[it.key()] = it.value(); } hashList << map; } settings->setArray("apps", hashList); } int UKUITaskBar::indexOfButton(UKUITaskGroup* button) const { return mLayout->indexOf(button); } int UKUITaskBar::countOfButtons() const { return mLayout->count(); } void UKUITaskBar::wl_kwinSigHandler(quint32 wl_winId, int opNo, QString wl_iconName, QString wl_caption) { qDebug()<<"UKUITaskBar::wl_kwinSigHandler"<setActivateState_wl(false); break; case 2: onWindowRemoved(wl_winId); break; case 3: mKnownWindows.find(wl_winId).value()->setActivateState_wl(true); break; case 4: addWindow_wl(wl_iconName, wl_caption, wl_winId); mKnownWindows.find(wl_winId).value()->wl_widgetUpdateTitle(wl_caption); break; } } void UKUITaskBar::addWindow_wl(QString iconName, QString caption, WId window) { // If grouping disabled group behaves like regular button // QString temp_group_id=caption; // QStringList strList = temp_group_id.split(" "); const QString group_id = captionExchange(caption); if (QIcon::fromTheme(group_id).isNull()) { iconName = QDir::homePath() + "/.local/share/icons/" + group_id + ".svg"; if (!isFileExit(iconName)) { iconName = QDir::homePath() + "/.local/share/icons/" + group_id + ".png"; if (!isFileExit(iconName)) { iconName = group_id; } } } else { iconName = group_id; } UKUITaskGroup *group = nullptr; auto i_group = mKnownWindows.find(window); if (mKnownWindows.end() != i_group) { if ((*i_group)->groupName() == group_id) group = *i_group; else (*i_group)->onWindowRemoved(window); } if (!group && mGroupingEnabled && group_id.compare("kylin-video")) { for (auto i = mKnownWindows.cbegin(), i_e = mKnownWindows.cend(); i != i_e; ++i) { if ((*i)->groupName() == group_id) { group = *i; break; } } } if (!group) { group = new UKUITaskGroup(iconName, caption, window, this); mPlaceHolder->hide(); connect(group, SIGNAL(groupBecomeEmpty(QString)), this, SLOT(groupBecomeEmptySlot())); connect(group, SIGNAL(visibilityChanged(bool)), this, SLOT(refreshPlaceholderVisibility())); connect(group, &UKUITaskGroup::popupShown, this, &UKUITaskBar::popupShown); connect(group, &UKUITaskButton::dragging, this, [this] (QObject * dragSource, QPoint const & pos) { buttonMove(qobject_cast(sender()), qobject_cast(dragSource), pos); }); //wayland临时图标适配主题代码处理 /*********************************************/ if(QIcon::fromTheme(group_id).hasThemeIcon(group_id)){ group->setIcon(QIcon::fromTheme(group_id)); }else{ group->setIcon(QIcon::fromTheme(iconName)); } connect(changeTheme, &QGSettings::changed, this, [=] (const QString &key){ if(key=="iconThemeName"){ sleep(1); if(QIcon::fromTheme(group_id).hasThemeIcon(group_id)){ group->setIcon(QIcon::fromTheme(group_id)); }else{ group->setIcon(QIcon::fromTheme(iconName)); } } }); /*********************************************/ // group->setFixedSize(panel()->panelSize(),panel()->panelSize()); //group->setFixedSize(40,40); mLayout->addWidget(group) ; group->wl_widgetUpdateTitle(caption); group->setStyle(new CustomStyle("taskbutton")); group->setToolButtonsStyle(mButtonStyle); } mKnownWindows[window] = group; group->wl_addWindow(window); } QString UKUITaskBar::captionExchange(QString str) { QString temp_group_id=str; QStringList strList = temp_group_id.split(" "); QString group_id = strList[0]; QStringList video_list; if(mAndroidIconHash.keys().contains(temp_group_id)){ group_id=mAndroidIconHash.value(temp_group_id); }else{ video_list<<"影音"<<"Video"; if(video_list.contains(group_id)) group_id ="kylin-video"; else group_id="application-x-desktop"; } return group_id; } QHash UKUITaskBar::matchAndroidIcon() { QHash hash; printf("*************\n"); QFile file("/usr/share/ukui/ukui-panel/plugin-taskbar/name-icon.match"); if(!file.open(QIODevice::ReadOnly)) qDebug()<<"Read FIle failed"; while (!file.atEnd()){ QByteArray line= file.readLine(); QString str=file.readLine(); str.section('picture',1,1).trimmed().toStdString(); str.simplified(); QString str_name = str.section(QRegExp("[;]"),0,0); str_name = str_name.simplified(); str_name = str_name.remove("name="); QString str_icon = str.section(QRegExp("[;]"),1,1); str_icon = str_icon.simplified(); str_icon = str_icon.remove("icon="); hash.insert(str_name,str_icon); } return hash; } ukui-panel-3.0.6.4/plugin-taskbar/ukuitaskclosebutton.cpp0000644000175000017500000000401314203402514022116 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include "ukuitaskclosebutton.h" #include "../panel/customstyle.h" #include "../panel/highlight-effect.h" UKUITaskCloseButton::UKUITaskCloseButton(const WId window, QWidget *parent): QToolButton(parent), mWindow(window) { this->setStyle(new CustomStyle("closebutton")); this->setIcon(QIcon(HighLightEffect::drawSymbolicColoredPixmap(QPixmap::fromImage(QIcon::fromTheme("window-close-symbolic").pixmap(24,24).toImage())))); this->setIconSize(QSize(9,9)); //connect(parent, &UKUITaskBar::buttonRotationRefreshed, this, &UKUITaskGroup::setAutoRotation); } /************************************************ ************************************************/ void UKUITaskCloseButton::mousePressEvent(QMouseEvent* event) { // const Qt::MouseButton b = event->button(); // if (Qt::LeftButton == b) // mDragStartPosition = event->pos(); // else if (Qt::MidButton == b && parentTaskBar()->closeOnMiddleClick()) // closeApplication(); QToolButton::mousePressEvent(event); } /************************************************ ************************************************/ void UKUITaskCloseButton::mouseReleaseEvent(QMouseEvent* event) { if (event->button()== Qt::LeftButton) { emit sigClicked(); } QToolButton::mouseReleaseEvent(event); } ukui-panel-3.0.6.4/plugin-taskbar/ukuitaskbutton.cpp0000644000175000017500000006456014203402514021105 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2011 Razor team * 2014 LXQt team * Authors: * Alexander Sokoloff * Kuzma Shapran * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "ukuitaskbutton.h" #include "ukuitaskgroup.h" #include "ukuitaskbar.h" //#include #include "../panel/common/ukuisettings.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ukuitaskgroup.h" #include "ukuitaskbar.h" #include "../panel/customstyle.h" #include // Necessary for closeApplication() #include #include #include "../panel/iukuipanelplugin.h" #include "../panel/highlight-effect.h" #include #include #include #include #include #include #include #include #include #define UKUI_PANEL_SETTINGS "org.ukui.panel.settings" #define PANELPOSITION "panelposition" #define PANEL_SETTINGS "org.ukui.panel.settings" #define PANEL_SIZE_KEY "panelsize" #define ICON_SIZE_KEY "iconsize" #define PANEL_POSITION_KEY "panelposition" bool UKUITaskButton::sDraggging = false; /************************************************ ************************************************/ void LeftAlignedTextStyle::drawItemText(QPainter * painter, const QRect & rect, int flags , const QPalette & pal, bool enabled, const QString & text , QPalette::ColorRole textRole) const { QString txt = QFontMetrics(painter->font()).elidedText(text, Qt::ElideRight, rect.width()); return QProxyStyle::drawItemText(painter, rect, (flags & ~Qt::AlignHCenter) | Qt::AlignLeft, pal, enabled, txt, textRole); } /************************************************ ************************************************/ UKUITaskButton::UKUITaskButton(QString appName,const WId window, UKUITaskBar * taskbar, QWidget *parent) : QToolButton(parent), mWindow(window), mAppName(appName), mUrgencyHint(false), mOrigin(Qt::TopLeftCorner), mDrawPixmap(false), mParentTaskBar(taskbar), mPlugin(mParentTaskBar->plugin()), mDNDTimer(new QTimer(this)) { Q_ASSERT(taskbar); taskbuttonstatus=NORMAL; setCheckable(true); setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); setMinimumWidth(1); setMinimumHeight(1); setToolButtonStyle(Qt::ToolButtonTextBesideIcon); setAcceptDrops(true); updateText(); updateIcon(); mDNDTimer->setSingleShot(true); mDNDTimer->setInterval(700); connect(mDNDTimer, SIGNAL(timeout()), this, SLOT(activateWithDraggable())); connect(UKUi::Settings::globalSettings(), SIGNAL(iconThemeChanged()), this, SLOT(updateIcon())); connect(mParentTaskBar, &UKUITaskBar::iconByClassChanged, this, &UKUITaskButton::updateIcon); const QByteArray id(PANEL_SETTINGS); gsettings = new QGSettings(id); connect(gsettings, &QGSettings::changed, this, [=] (const QString &key){ if (key == PANEL_SIZE_KEY) { updateIcon(); } }); } UKUITaskButton::UKUITaskButton(QString iconName,QString caption, const WId window, UKUITaskBar * taskbar, QWidget *parent) : QToolButton(parent), mIconName(iconName), mCaption(caption), mWindow(window), mParentTaskBar(taskbar), mPlugin(mParentTaskBar->plugin()) { setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); isWinActivate = true; mIcon = QIcon::fromTheme("application-x-desktop"); } /************************************************ ************************************************/ UKUITaskButton::~UKUITaskButton() { } /************************************************ ************************************************/ void UKUITaskButton::updateText() { KWindowInfo info(mWindow, NET::WMVisibleName | NET::WMName); QString title = info.visibleName().isEmpty() ? info.name() : info.visibleName(); setText(title.replace("&", "&&")); setToolTip(title); } void UKUITaskButton::setLeaderWindow(WId leaderWindow) { mWindow = leaderWindow; } /* int devicePixels = mPlugin->panel()->iconSize() * devicePixelRatioF()是由ico =KWindowSystem:ico(mwindow)更改的 * 目的是为了能够显示正确的application-x-desktop的图标的大小 * */ void UKUITaskButton::updateIcon() { if (mAppName == QString("emo-system-ShellMethods") || mAppName == QString("Qq")) sleep(1); QIcon ico; int mIconSize=mPlugin->panel()->iconSize(); if (mParentTaskBar->isIconByClass()) { ico = QIcon::fromTheme(QString::fromUtf8(KWindowInfo{mWindow, 0, NET::WM2WindowClass}.windowClassClass()).toLower()); } if (ico.isNull()) { #if QT_VERSION >= 0x050600 int devicePixels = mIconSize * devicePixelRatioF(); #else int devicePixels = mIconSize * devicePixelRatio(); #endif ico = KWindowSystem::icon(mWindow, devicePixels, devicePixels); } if (mIcon.isNull()) mIcon = QIcon::fromTheme("application-x-desktop"); setIcon(ico.isNull() ? mIcon : ico); setIconSize(QSize(mIconSize,mIconSize)); } void UKUITaskButton::setGroupIcon(QIcon ico) { mIcon = ico; } /************************************************ ************************************************/ void UKUITaskButton::refreshIconGeometry(QRect const & geom) { NETWinInfo info(QX11Info::connection(), windowId(), (WId) QX11Info::appRootWindow(), NET::WMIconGeometry, 0); NETRect const curr = info.iconGeometry(); if (curr.pos.x != geom.x() || curr.pos.y != geom.y() || curr.size.width != geom.width() || curr.size.height != geom.height()) { NETRect nrect; nrect.pos.x = geom.x(); nrect.pos.y = geom.y(); nrect.size.height = geom.height(); nrect.size.width = geom.width(); info.setIconGeometry(nrect); } } /************************************************ ************************************************/ void UKUITaskButton::dragEnterEvent(QDragEnterEvent *event) { // It must be here otherwise dragLeaveEvent and dragMoveEvent won't be called // on the other hand drop and dragmove events of parent widget won't be called event->acceptProposedAction(); if (event->mimeData()->hasFormat(mimeDataFormat())) { emit dragging(event->source(), event->pos()); setAttribute(Qt::WA_UnderMouse, false); } else { mDNDTimer->start(); } QToolButton::dragEnterEvent(event); } void UKUITaskButton::dragMoveEvent(QDragMoveEvent * event) { if (event->mimeData()->hasFormat(mimeDataFormat())) { emit dragging(event->source(), event->pos()); setAttribute(Qt::WA_UnderMouse, false); } } void UKUITaskButton::dragLeaveEvent(QDragLeaveEvent *event) { mDNDTimer->stop(); QToolButton::dragLeaveEvent(event); } void UKUITaskButton::dropEvent(QDropEvent *event) { mDNDTimer->stop(); if (event->mimeData()->hasFormat(mimeDataFormat())) { //emit dropped(event->source(), event->pos()); setAttribute(Qt::WA_UnderMouse, false); } //QToolButton::dropEvent(event); } /************************************************ ************************************************/ void UKUITaskButton::mousePressEvent(QMouseEvent* event) { const Qt::MouseButton b = event->button(); if (Qt::LeftButton == b) { mDragStartPosition = event->pos(); } else if (statFlag && Qt::MidButton == b && parentTaskBar()->closeOnMiddleClick()) { closeApplication(); } QToolButton::mousePressEvent(event); } /************************************************ ************************************************/ void UKUITaskButton::mouseReleaseEvent(QMouseEvent* event) { // if (event->button() == Qt::LeftButton) // { // if (isChecked()) // minimizeApplication(); // else // { // raiseApplication(); // } // } QToolButton::mouseReleaseEvent(event); } /************************************************ ************************************************/ QMimeData * UKUITaskButton::mimeData() { QMimeData *mimedata = new QMimeData; QByteArray ba; QDataStream stream(&ba,QIODevice::WriteOnly); stream << (qlonglong)(mWindow); mimedata->setData(mimeDataFormat(), ba); return mimedata; } /************************************************ ************************************************/ void UKUITaskButton::mouseMoveEvent(QMouseEvent* event) { if (!(event->buttons() & Qt::LeftButton)) return; if ((event->pos() - mDragStartPosition).manhattanLength() < QApplication::startDragDistance()) return; QDrag *drag = new QDrag(this); drag->setMimeData(mimeData()); QIcon ico = icon(); QPixmap img = ico.pixmap(ico.actualSize({32, 32})); drag->setPixmap(img); switch (mPlugin->panel()->position()) { case IUKUIPanel::PositionLeft: case IUKUIPanel::PositionTop: drag->setHotSpot({0, 0}); break; case IUKUIPanel::PositionRight: case IUKUIPanel::PositionBottom: drag->setHotSpot(img.rect().bottomRight()); break; } sDraggging = true; drag->exec(); // if button is dropped out of panel (e.g. on desktop) // it is not deleted automatically by Qt drag->deleteLater(); sDraggging = false; QAbstractButton::mouseMoveEvent(event); } /************************************************ ************************************************/ bool UKUITaskButton::isApplicationHidden() const { KWindowInfo info(mWindow, NET::WMState); return (info.state() & NET::Hidden); } /************************************************ ************************************************/ bool UKUITaskButton::isApplicationActive() const { return KWindowSystem::activeWindow() == mWindow; } /************************************************ ************************************************/ void UKUITaskButton::activateWithDraggable() { // raise app in any time when there is a drag // in progress to allow drop it into an app if (statFlag) { raiseApplication(); KWindowSystem::forceActiveWindow(mWindow); } } /************************************************ ************************************************/ void UKUITaskButton::raiseApplication() { KWindowInfo info(mWindow, NET::WMDesktop | NET::WMState | NET::XAWMState); if (parentTaskBar()->raiseOnCurrentDesktop() && info.isMinimized()) { KWindowSystem::setOnDesktop(mWindow, KWindowSystem::currentDesktop()); } else { int winDesktop = info.desktop(); if (KWindowSystem::currentDesktop() != winDesktop) KWindowSystem::setCurrentDesktop(winDesktop); } KWindowSystem::activateWindow(mWindow); setUrgencyHint(false); } /************************************************ ************************************************/ void UKUITaskButton::minimizeApplication() { KWindowSystem::minimizeWindow(mWindow); } /************************************************ ************************************************/ void UKUITaskButton::maximizeApplication() { QAction* act = qobject_cast(sender()); if (!act) return; int state = act->data().toInt(); switch (state) { case NET::MaxHoriz: KWindowSystem::setState(mWindow, NET::MaxHoriz); break; case NET::MaxVert: KWindowSystem::setState(mWindow, NET::MaxVert); break; default: KWindowSystem::setState(mWindow, NET::Max); break; } if (!isApplicationActive()) raiseApplication(); } /************************************************ ************************************************/ void UKUITaskButton::deMaximizeApplication() { KWindowSystem::clearState(mWindow, NET::Max); if (!isApplicationActive()) raiseApplication(); } /************************************************ ************************************************/ void UKUITaskButton::shadeApplication() { KWindowSystem::setState(mWindow, NET::Shaded); } /************************************************ ************************************************/ void UKUITaskButton::unShadeApplication() { KWindowSystem::clearState(mWindow, NET::Shaded); } /************************************************ ************************************************/ void UKUITaskButton::closeApplication() { // FIXME: Why there is no such thing in KWindowSystem?? NETRootInfo(QX11Info::connection(), NET::CloseWindow).closeWindowRequest(mWindow); } /************************************************ ************************************************/ void UKUITaskButton::setApplicationLayer() { QAction* act = qobject_cast(sender()); if (!act) return; int layer = act->data().toInt(); switch(layer) { case NET::KeepAbove: KWindowSystem::clearState(mWindow, NET::KeepBelow); KWindowSystem::setState(mWindow, NET::KeepAbove); break; case NET::KeepBelow: KWindowSystem::clearState(mWindow, NET::KeepAbove); KWindowSystem::setState(mWindow, NET::KeepBelow); break; default: KWindowSystem::clearState(mWindow, NET::KeepBelow); KWindowSystem::clearState(mWindow, NET::KeepAbove); break; } } /************************************************ ************************************************/ void UKUITaskButton::moveApplicationToDesktop() { QAction* act = qobject_cast(sender()); if (!act) return; bool ok; int desk = act->data().toInt(&ok); if (!ok) return; KWindowSystem::setOnDesktop(mWindow, desk); } /************************************************ ************************************************/ void UKUITaskButton::moveApplication() { KWindowInfo info(mWindow, NET::WMDesktop); if (!info.isOnCurrentDesktop()) KWindowSystem::setCurrentDesktop(info.desktop()); if (isMinimized()) KWindowSystem::unminimizeWindow(mWindow); KWindowSystem::forceActiveWindow(mWindow); const QRect& g = KWindowInfo(mWindow, NET::WMGeometry).geometry(); int X = g.center().x(); int Y = g.center().y(); QCursor::setPos(X, Y); NETRootInfo(QX11Info::connection(), NET::WMMoveResize).moveResizeRequest(mWindow, X, Y, NET::Move); } /************************************************ ************************************************/ void UKUITaskButton::resizeApplication() { KWindowInfo info(mWindow, NET::WMDesktop); if (!info.isOnCurrentDesktop()) KWindowSystem::setCurrentDesktop(info.desktop()); if (isMinimized()) KWindowSystem::unminimizeWindow(mWindow); KWindowSystem::forceActiveWindow(mWindow); const QRect& g = KWindowInfo(mWindow, NET::WMGeometry).geometry(); int X = g.bottomRight().x(); int Y = g.bottomRight().y(); QCursor::setPos(X, Y); NETRootInfo(QX11Info::connection(), NET::WMMoveResize).moveResizeRequest(mWindow, X, Y, NET::BottomRight); } /************************************************ ************************************************/ void UKUITaskButton::contextMenuEvent(QContextMenuEvent* event) { if (!statFlag) { return; } if (event->modifiers().testFlag(Qt::ControlModifier)) { event->ignore(); return; } KWindowInfo info(mWindow, 0, NET::WM2AllowedActions); unsigned long state = KWindowInfo(mWindow, NET::WMState).state(); QMenu * menu = new QMenu(tr("Application")); menu->setAttribute(Qt::WA_DeleteOnClose); QAction* a; /* KDE menu ******* + To &Desktop > + &All Desktops + --- + &1 Desktop 1 + &2 Desktop 2 + &To Current Desktop &Move Re&size + Mi&nimize + Ma&ximize + &Shade Ad&vanced > Keep &Above Others Keep &Below Others Fill screen &Layer > Always on &top &Normal Always on &bottom --- + &Close */ /********** Desktop menu **********/ int deskNum = KWindowSystem::numberOfDesktops(); if (deskNum > 1) { int winDesk = KWindowInfo(mWindow, NET::WMDesktop).desktop(); QMenu* deskMenu = menu->addMenu(tr("To &Desktop")); a = deskMenu->addAction(tr("&All Desktops")); a->setData(NET::OnAllDesktops); a->setEnabled(winDesk != NET::OnAllDesktops); connect(a, SIGNAL(triggered(bool)), this, SLOT(moveApplicationToDesktop())); deskMenu->addSeparator(); for (int i = 0; i < deskNum; ++i) { a = deskMenu->addAction(tr("Desktop &%1").arg(i + 1)); a->setData(i + 1); a->setEnabled(i + 1 != winDesk); connect(a, SIGNAL(triggered(bool)), this, SLOT(moveApplicationToDesktop())); } int curDesk = KWindowSystem::currentDesktop(); a = menu->addAction(tr("&To Current Desktop")); a->setData(curDesk); a->setEnabled(curDesk != winDesk); connect(a, SIGNAL(triggered(bool)), this, SLOT(moveApplicationToDesktop())); } /********** Move/Resize **********/ menu->addSeparator(); a = menu->addAction(tr("&Move")); a->setEnabled(info.actionSupported(NET::ActionMove) && !(state & NET::Max) && !(state & NET::FullScreen)); connect(a, &QAction::triggered, this, &UKUITaskButton::moveApplication); a = menu->addAction(tr("Resi&ze")); a->setEnabled(info.actionSupported(NET::ActionResize) && !(state & NET::Max) && !(state & NET::FullScreen)); connect(a, &QAction::triggered, this, &UKUITaskButton::resizeApplication); /********** State menu **********/ menu->addSeparator(); a = menu->addAction(tr("Ma&ximize")); a->setEnabled(info.actionSupported(NET::ActionMax) && (!(state & NET::Max) || (state & NET::Hidden))); a->setData(NET::Max); connect(a, SIGNAL(triggered(bool)), this, SLOT(maximizeApplication())); if (event->modifiers() & Qt::ShiftModifier) { a = menu->addAction(tr("Maximize vertically")); a->setEnabled(info.actionSupported(NET::ActionMaxVert) && !((state & NET::MaxVert) || (state & NET::Hidden))); a->setData(NET::MaxVert); connect(a, SIGNAL(triggered(bool)), this, SLOT(maximizeApplication())); a = menu->addAction(tr("Maximize horizontally")); a->setEnabled(info.actionSupported(NET::ActionMaxHoriz) && !((state & NET::MaxHoriz) || (state & NET::Hidden))); a->setData(NET::MaxHoriz); connect(a, SIGNAL(triggered(bool)), this, SLOT(maximizeApplication())); } a = menu->addAction(tr("&Restore")); a->setEnabled((state & NET::Hidden) || (state & NET::Max) || (state & NET::MaxHoriz) || (state & NET::MaxVert)); connect(a, SIGNAL(triggered(bool)), this, SLOT(deMaximizeApplication())); a = menu->addAction(tr("Mi&nimize")); a->setEnabled(info.actionSupported(NET::ActionMinimize) && !(state & NET::Hidden)); connect(a, SIGNAL(triggered(bool)), this, SLOT(minimizeApplication())); if (state & NET::Shaded) { a = menu->addAction(tr("Roll down")); a->setEnabled(info.actionSupported(NET::ActionShade) && !(state & NET::Hidden)); connect(a, SIGNAL(triggered(bool)), this, SLOT(unShadeApplication())); } else { a = menu->addAction(tr("Roll up")); a->setEnabled(info.actionSupported(NET::ActionShade) && !(state & NET::Hidden)); connect(a, SIGNAL(triggered(bool)), this, SLOT(shadeApplication())); } /********** Layer menu **********/ menu->addSeparator(); QMenu* layerMenu = menu->addMenu(tr("&Layer")); a = layerMenu->addAction(tr("Always on &top")); // FIXME: There is no info.actionSupported(NET::ActionKeepAbove) a->setEnabled(!(state & NET::KeepAbove)); a->setData(NET::KeepAbove); connect(a, SIGNAL(triggered(bool)), this, SLOT(setApplicationLayer())); a = layerMenu->addAction(tr("&Normal")); a->setEnabled((state & NET::KeepAbove) || (state & NET::KeepBelow)); // FIXME: There is no NET::KeepNormal, so passing 0 a->setData(0); connect(a, SIGNAL(triggered(bool)), this, SLOT(setApplicationLayer())); a = layerMenu->addAction(tr("Always on &bottom")); // FIXME: There is no info.actionSupported(NET::ActionKeepBelow) a->setEnabled(!(state & NET::KeepBelow)); a->setData(NET::KeepBelow); connect(a, SIGNAL(triggered(bool)), this, SLOT(setApplicationLayer())); /********** Kill menu **********/ menu->addSeparator(); a = menu->addAction(QIcon::fromTheme("process-stop"), tr("&Close")); connect(a, SIGNAL(triggered(bool)), this, SLOT(closeApplication())); menu->setGeometry(mParentTaskBar->panel()->calculatePopupWindowPos(mapToGlobal(event->pos()), menu->sizeHint())); mPlugin->willShowWindow(menu); menu->show(); } /************************************************ ************************************************/ void UKUITaskButton::setUrgencyHint(bool set) { if (mUrgencyHint == set) return; if (!set) KWindowSystem::demandAttention(mWindow, false); mUrgencyHint = set; setProperty("urgent", set); style()->unpolish(this); style()->polish(this); update(); } bool UKUITaskButton::isOnDesktop(int desktop) const { return KWindowInfo(mWindow, NET::WMDesktop).isOnDesktop(desktop); } bool UKUITaskButton::isOnCurrentScreen() const { return QApplication::desktop()->screenGeometry(parentTaskBar()).intersects(KWindowInfo(mWindow, NET::WMFrameExtents).frameGeometry()); } bool UKUITaskButton::isMinimized() const { return KWindowInfo(mWindow,NET::WMState | NET::XAWMState).isMinimized(); } Qt::Corner UKUITaskButton::origin() const { return mOrigin; } void UKUITaskButton::setOrigin(Qt::Corner newOrigin) { if (mOrigin != newOrigin) { mOrigin = newOrigin; update(); } } void UKUITaskButton::setAutoRotation(bool value, IUKUIPanel::Position position) { if (value) { switch (position) { case IUKUIPanel::PositionTop: case IUKUIPanel::PositionBottom: setOrigin(Qt::TopLeftCorner); break; case IUKUIPanel::PositionLeft: setOrigin(Qt::BottomLeftCorner); break; case IUKUIPanel::PositionRight: setOrigin(Qt::TopRightCorner); break; } } else setOrigin(Qt::TopLeftCorner); } void UKUITaskButton::enterEvent(QEvent *) { taskbuttonstatus=HOVER; update(); } void UKUITaskButton::leaveEvent(QEvent *) { taskbuttonstatus=NORMAL; update(); } /*在paintEvent中执行绘图事件会造成高分屏下图片模糊 * 高分屏的图片模糊问题大概率与svg/png图片无关 * */ void UKUITaskButton::paintEvent(QPaintEvent *event) { QToolButton::paintEvent(event); return; } bool UKUITaskButton::hasDragAndDropHover() const { return mDNDTimer->isActive(); } UKUITaskButton::UKUITaskButton(QuickLaunchAction * act, IUKUIPanelPlugin * plugin, QWidget * parent) : QToolButton(parent), mAct(act), mPlugin(plugin) { mDNDTimer = new QTimer(this); statFlag = false; setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); /*设置快速启动栏的按键不接受焦点*/ setFocusPolicy(Qt::NoFocus); setAutoRaise(true); quicklanuchstatus = NORMAL; setDefaultAction(mAct); mAct->setParent(this); /*设置快速启动栏的菜单项*/ const QByteArray id(UKUI_PANEL_SETTINGS); mgsettings = new QGSettings(id); modifyQuicklaunchMenuAction(true); connect(mgsettings, &QGSettings::changed, this, [=] (const QString &key){ if(key==PANELPOSITION){ modifyQuicklaunchMenuAction(true); } }); setContextMenuPolicy(Qt::CustomContextMenu); connect(this, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(this_customContextMenuRequested(const QPoint&))); mDNDTimer->setSingleShot(true); mDNDTimer->setInterval(700); connect(mDNDTimer, SIGNAL(timeout()), this, SLOT(activateWithDraggable())); file_name=act->m_settingsMap["desktop"]; this->setStyle(new CustomStyle()); repaint(); } QHash UKUITaskButton::settingsMap() { Q_ASSERT(mAct); return mAct->settingsMap(); } /*与鼠标右键的选项有关*/ void UKUITaskButton::this_customContextMenuRequested(const QPoint & pos) { mPlugin->willShowWindow(mMenu); mMenu->popup(mPlugin->panel()->calculatePopupWindowPos(mapToGlobal({0, 0}), mMenu->sizeHint()).topLeft()); } /*调整快速启动栏的菜单项*/ void UKUITaskButton::modifyQuicklaunchMenuAction(bool direction) { mDeleteAct = new QAction(HighLightEffect::drawSymbolicColoredIcon(QIcon::fromTheme("ukui-unfixed")), tr("delete from quicklaunch"), this); connect(mDeleteAct, SIGNAL(triggered()), this, SLOT(selfRemove())); //addAction(mDeleteAct); mMenu = new QuicklaunchMenu(); mMenu->addAction(mAct); mMenu->addActions(mAct->addtitionalActions()); mMenu->addSeparator(); mMenu->addSeparator(); mMenu->addAction(mDeleteAct); } void UKUITaskButton::selfRemove() { emit buttonDeleted(); } QuicklaunchMenu::QuicklaunchMenu() { } QuicklaunchMenu::~QuicklaunchMenu() { } void QuicklaunchMenu::contextMenuEvent(QContextMenuEvent *) { } ukui-panel-3.0.6.4/plugin-taskbar/ukuitaskwidget.cpp0000644000175000017500000007261214203402514021052 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include "../panel/common/ukuisettings.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ukuitaskgroup.h" #include "ukuitaskbar.h" #include "ukuitaskclosebutton.h" #include // Necessary for closeApplication() #include #include #define WAYLAND_GROUP_HIDE 0 #define WAYLAND_GROUP_ACTIVATE 1 #define WAYLAND_GROUP_CLOSE 2 bool UKUITaskWidget::sDraggging = false; /************************************************ ************************************************/ //void LeftAlignedTextStyle::drawItemText(QPainter * painter, const QRect & rect, int flags // , const QPalette & pal, bool enabled, const QString & text // , QPalette::ColorRole textRole) const //{ // QString txt = QFontMetrics(painter->font()).elidedText(text, Qt::ElideRight, rect.width()); // return QProxyStyle::drawItemText(painter, rect, (flags & ~Qt::AlignHCenter) | Qt::AlignLeft, pal, enabled, txt, textRole); //} /************************************************ ************************************************/ UKUITaskWidget::UKUITaskWidget(const WId window, UKUITaskBar * taskbar, QWidget *parent) : QWidget(parent), mWindow(window), mUrgencyHint(false), mOrigin(Qt::TopLeftCorner), mDrawPixmap(false), mParentTaskBar(taskbar), mPlugin(mParentTaskBar->plugin()), mDNDTimer(new QTimer(this)) { Q_ASSERT(taskbar); setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); setMinimumWidth(1); setMinimumHeight(1); setAcceptDrops(true); // QPixmap closePix = style()->standardPixmap(QStyle::SP_TitleBarCloseButton); status=NORMAL; setAttribute(Qt::WA_TranslucentBackground);//设置窗口背景透明 setWindowFlags(Qt::FramelessWindowHint); //设置无边框窗口 //for layout mCloseBtn = new UKUITaskCloseButton(mWindow, this); // mCloseBtn->setIcon(QIcon::fromTheme("window-close-symbolic")); mCloseBtn->setIconSize(QSize(19,19)); mCloseBtn->setFixedSize(QSize(19,19)); mTitleLabel = new QLabel(this); mTitleLabel->setMargin(0); // mTitleLabel->setContentsMargins(0,0,0,10); // mTitleLabel->adjustSize(); // mTitleLabel->setStyleSheet("QLabel{background-color: red;}"); mThumbnailLabel = new QLabel(this); mAppIcon = new QLabel(this); mVWindowsLayout = new QVBoxLayout(this); mTopBarLayout = new QHBoxLayout(this); mTopBarLayout->setContentsMargins(0,0,0,0); // mTopBarLayout->setAlignment(Qt::AlignVCenter); // mTopBarLayout->setDirection(QBoxLayout::LeftToRight); mTitleLabel->setAlignment(Qt::AlignLeft | Qt::AlignVCenter); mAppIcon->setAlignment(Qt::AlignLeft); mAppIcon->setScaledContents(false); // 自动缩放图片 // titleLabel->setScaledContents(true); mThumbnailLabel->setScaledContents(true); // 设置控件缩放方式 QSizePolicy sizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); sizePolicy.setHorizontalPolicy(QSizePolicy::Expanding); mTitleLabel->setSizePolicy(sizePolicy); mAppIcon->setSizePolicy(sizePolicy); sizePolicy.setVerticalPolicy(QSizePolicy::Expanding); // mTitleLabel->setAttribute(Qt::WA_TranslucentBackground, true); // mAppIcon->setAttribute(Qt::WA_TranslucentBackground, true); // mAppIcon->resize(QSize(32,32)); // 设置控件最大尺寸 //mTitleLabel->setFixedHeight(32); mTitleLabel->setMinimumWidth(1); mThumbnailLabel->setMinimumSize(QSize(1, 1)); mTitleLabel->setContentsMargins(0, 0, 5, 0); // mTopBarLayout->setSpacing(5); mTopBarLayout->addWidget(mAppIcon, 0, Qt::AlignLeft | Qt::AlignVCenter); mTopBarLayout->addWidget(mTitleLabel, 10, Qt::AlignLeft); mTopBarLayout->addWidget(mCloseBtn, 0, Qt::AlignRight); // mTopBarLayout->addStretch(); // mTopBarLayout->addWidget(mCloseBtn, 0, Qt::AlignRight | Qt::AlignVCenter); // mVWindowsLayout->setAlignment(Qt::AlignCenter); mVWindowsLayout->addLayout(mTopBarLayout); mVWindowsLayout->addWidget(mThumbnailLabel, Qt::AlignCenter, Qt::AlignCenter); mVWindowsLayout->setSizeConstraint(QLayout::SetMinAndMaxSize); this->setLayout(mVWindowsLayout); updateText(); updateIcon(); mDNDTimer->setSingleShot(true); mDNDTimer->setInterval(700); connect(mDNDTimer, SIGNAL(timeout()), this, SLOT(activateWithDraggable())); connect(UKUi::Settings::globalSettings(), SIGNAL(iconThemeChanged()), this, SLOT(updateIcon())); connect(mParentTaskBar, &UKUITaskBar::iconByClassChanged, this, &UKUITaskWidget::updateIcon); connect(mCloseBtn, SIGNAL(sigClicked()), this, SLOT(closeApplication())); } UKUITaskWidget::UKUITaskWidget(QString iconName, const WId window, UKUITaskBar * taskbar, QWidget *parent) : QWidget(parent), mParentTaskBar(taskbar), mWindow(window), mDNDTimer(new QTimer(this)) { isWaylandWidget = true; //setMinimumWidth(400); //setMinimumHeight(400); status=NORMAL; setAttribute(Qt::WA_TranslucentBackground);//设置窗口背景透明 setWindowFlags(Qt::FramelessWindowHint); //设置无边框窗口 //for layout mCloseBtn = new UKUITaskCloseButton(mWindow, this); // mCloseBtn->setIcon(QIcon::fromTheme("window-close-symbolic")); mCloseBtn->setIconSize(QSize(19,19)); mCloseBtn->setFixedSize(QSize(19,19)); mTitleLabel = new QLabel(this); mTitleLabel->setMargin(0); // mTitleLabel->setContentsMargins(0,0,0,10); // mTitleLabel->adjustSize(); // mTitleLabel->setStyleSheet("QLabel{background-color: red;}"); mThumbnailLabel = new QLabel(this); mAppIcon = new QLabel(this); mVWindowsLayout = new QVBoxLayout(this); mTopBarLayout = new QHBoxLayout(this); mTopBarLayout->setContentsMargins(0,0,0,0); // mTopBarLayout->setAlignment(Qt::AlignVCenter); // mTopBarLayout->setDirection(QBoxLayout::LeftToRight); mTitleLabel->setAlignment(Qt::AlignLeft | Qt::AlignVCenter); mAppIcon->setAlignment(Qt::AlignLeft); mAppIcon->setScaledContents(false); // 自动缩放图片 // titleLabel->setScaledContents(true); mThumbnailLabel->setScaledContents(true); // 设置控件缩放方式 QSizePolicy sizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); sizePolicy.setHorizontalPolicy(QSizePolicy::Expanding); mTitleLabel->setSizePolicy(sizePolicy); mAppIcon->setSizePolicy(sizePolicy); sizePolicy.setVerticalPolicy(QSizePolicy::Expanding); // mTitleLabel->setAttribute(Qt::WA_TranslucentBackground, true); // mAppIcon->setAttribute(Qt::WA_TranslucentBackground, true); // mAppIcon->resize(QSize(32,32)); // 设置控件最大尺寸 //mTitleLabel->setFixedHeight(32); mTitleLabel->setMinimumWidth(1); mThumbnailLabel->setMinimumSize(QSize(1, 1)); mThumbnailLabel->setMaximumSize(QSize(this->width()*2,this->height()*8)); mTitleLabel->setContentsMargins(0, 0, 5, 0); // mTopBarLayout->setSpacing(5); mTopBarLayout->addWidget(mAppIcon, 0, Qt::AlignLeft | Qt::AlignVCenter); mTopBarLayout->addWidget(mTitleLabel, 10, Qt::AlignLeft); mTopBarLayout->addWidget(mCloseBtn, 0, Qt::AlignRight); // mTopBarLayout->addStretch(); // mTopBarLayout->addWidget(mCloseBtn, 0, Qt::AlignRight | Qt::AlignVCenter); // mVWindowsLayout->setAlignment(Qt::AlignCenter); mVWindowsLayout->addLayout(mTopBarLayout); mVWindowsLayout->addWidget(mThumbnailLabel, Qt::AlignCenter, Qt::AlignCenter); mVWindowsLayout->setSizeConstraint(QLayout::SetMinAndMaxSize); this->setLayout(mVWindowsLayout); updateText(); updateIcon(); mDNDTimer->setSingleShot(true); mDNDTimer->setInterval(700); connect(mDNDTimer, SIGNAL(timeout()), this, SLOT(activateWithDraggable())); connect(UKUi::Settings::globalSettings(), SIGNAL(iconThemeChanged()), this, SLOT(updateIcon())); connect(mParentTaskBar, &UKUITaskBar::iconByClassChanged, this, &UKUITaskWidget::updateIcon); connect(mCloseBtn, SIGNAL(sigClicked()), this, SLOT(closeApplication())); } /************************************************ ************************************************/ UKUITaskWidget::~UKUITaskWidget() { this->deleteLater(); } /************************************************ ************************************************/ void UKUITaskWidget::updateText() { KWindowInfo info(mWindow, NET::WMVisibleName | NET::WMName); QString title = info.visibleName().isEmpty() ? info.name() : info.visibleName(); mTitleLabel->setToolTip(title); QTimer::singleShot(0,this,[=](){ QString formatAppName = mTitleLabel->fontMetrics().elidedText(title,Qt::ElideRight, mTitleLabel->width()); mTitleLabel->setText(formatAppName); QPalette pa; pa.setColor(QPalette::WindowText,Qt::white); mTitleLabel->setPalette(pa); }); // mTitleLabel->setText(title); // setText(title.replace("&", "&&")); // setToolTip(title); } /************************************************ ************************************************/ void UKUITaskWidget::updateIcon() { QIcon ico; if (mParentTaskBar->isIconByClass()) { ico = QIcon::fromTheme(QString::fromUtf8(KWindowInfo{mWindow, 0, NET::WM2WindowClass}.windowClassClass()).toLower()); } if (ico.isNull()) { ico = KWindowSystem::icon(mWindow); } mAppIcon->setPixmap(ico.pixmap(QSize(19,19))); setPixmap(KWindowSystem::icon(mWindow)); // mPixmap = ico.pixmap(QSize(64,64); //mAppIcon->setWindowIcon(ico.isNull() ? XdgIcon::defaultApplicationIcon() : ico); //setIcon(ico.isNull() ? XdgIcon::defaultApplicationIcon() : ico); } void UKUITaskWidget::setPixmap(QPixmap _pixmap) { mPixmap = _pixmap; } QPixmap UKUITaskWidget::getPixmap() { return mPixmap; } /************************************************ ************************************************/ void UKUITaskWidget::refreshIconGeometry(QRect const & geom) { NETWinInfo info(QX11Info::connection(), windowId(), (WId) QX11Info::appRootWindow(), NET::WMIconGeometry, 0); NETRect const curr = info.iconGeometry(); if (curr.pos.x != geom.x() || curr.pos.y != geom.y() || curr.size.width != geom.width() || curr.size.height != geom.height()) { NETRect nrect; nrect.pos.x = geom.x(); nrect.pos.y = geom.y(); nrect.size.height = geom.height(); nrect.size.width = geom.width(); info.setIconGeometry(nrect); } } /************************************************ ************************************************/ void UKUITaskWidget::dragEnterEvent(QDragEnterEvent *event) { // It must be here otherwise dragLeaveEvent and dragMoveEvent won't be called // on the other hand drop and dragmove events of parent widget won't be called event->acceptProposedAction(); if (event->mimeData()->hasFormat(mimeDataFormat())) { emit dragging(event->source(), event->pos()); setAttribute(Qt::WA_UnderMouse, false); } else { mDNDTimer->start(); } QWidget::dragEnterEvent(event); } void UKUITaskWidget::dragMoveEvent(QDragMoveEvent * event) { if (event->mimeData()->hasFormat(mimeDataFormat())) { emit dragging(event->source(), event->pos()); setAttribute(Qt::WA_UnderMouse, false); } } void UKUITaskWidget::dragLeaveEvent(QDragLeaveEvent *event) { mDNDTimer->stop(); QWidget::dragLeaveEvent(event); } void UKUITaskWidget::dropEvent(QDropEvent *event) { mDNDTimer->stop(); if (event->mimeData()->hasFormat(mimeDataFormat())) { emit dropped(event->source(), event->pos()); setAttribute(Qt::WA_UnderMouse, false); } QWidget::dropEvent(event); } /************************************************ ************************************************/ void UKUITaskWidget::mousePressEvent(QMouseEvent* event) { const Qt::MouseButton b = event->button(); if (Qt::LeftButton == b) { mDragStartPosition = event->pos(); } else if (Qt::MidButton == b && parentTaskBar()->closeOnMiddleClick()) closeApplication(); QWidget::mousePressEvent(event); } /************************************************ ************************************************/ void UKUITaskWidget::mouseReleaseEvent(QMouseEvent* event) { if (event->button() == Qt::LeftButton) { // if (isChecked()) // minimizeApplication(); // else raiseApplication(); } status = NORMAL; update(); QWidget::mouseReleaseEvent(event); } /************************************************ ************************************************/ void UKUITaskWidget::enterEvent(QEvent *) { status = HOVER; repaint(); } void UKUITaskWidget::leaveEvent(QEvent *) { status = NORMAL; repaint(); } QMimeData * UKUITaskWidget::mimeData() { QMimeData *mimedata = new QMimeData; QByteArray ba; QDataStream stream(&ba,QIODevice::WriteOnly); stream << (qlonglong)(mWindow); mimedata->setData(mimeDataFormat(), ba); return mimedata; } /************************************************ ************************************************/ void UKUITaskWidget::mouseMoveEvent(QMouseEvent* event) { } void UKUITaskWidget::closeGroup() { emit closeSigtoGroup(); } void UKUITaskWidget::contextMenuEvent(QContextMenuEvent *event) { KWindowInfo info(mWindow, 0, NET::WM2AllowedActions); unsigned long state = KWindowInfo(mWindow, NET::WMState).state(); if (!mPlugin || isWaylandWidget) return; QMenu * menu = new QMenu(tr("Widget")); menu->setAttribute(Qt::WA_DeleteOnClose); /* 对应预览图右键功能 关闭 还原 最大化 最小化 置顶 取消置顶*/ QAction *close = menu->addAction(QIcon::fromTheme("window-close-symbolic"), tr("close")); QAction *restore = menu->addAction(QIcon::fromTheme("window-restore-symbolic"), tr("restore")); QAction *maxim = menu->addAction(QIcon::fromTheme("window-maximize-symbolic"), tr("maximaze")); maxim->setEnabled(info.actionSupported(NET::ActionMax) && (!(state & NET::Max) || (state & NET::Hidden))); QAction *minim = menu->addAction(QIcon::fromTheme("window-minimize-symbolic"), tr("minimize")); QAction *above = menu->addAction(QIcon::fromTheme("ukui-fixed"), tr("above")); QAction *clear = menu->addAction(QIcon::fromTheme("ukui-unfixed"), tr("clear")); connect(close, SIGNAL(triggered()), this, SLOT(closeApplication())); connect(restore, SIGNAL(triggered()), this, SLOT(deMaximizeApplication())); connect(maxim, SIGNAL(triggered()), this, SLOT(maximizeApplication())); connect(minim, SIGNAL(triggered()), this, SLOT(minimizeApplication())); connect(above, SIGNAL(triggered()), this, SLOT(setWindowKeepAbove())); connect(clear, SIGNAL(triggered()), this, SLOT(setWindowStatusClear())); connect(menu, &QMenu::aboutToHide, [this] { emit closeSigtoPop(); }); above->setEnabled(!(state & NET::KeepAbove)); clear->setEnabled(state & NET::KeepAbove); menu->exec(cursor().pos()); plugin()->willShowWindow(menu); if (!isWaylandWidget) menu->show(); } /************************************************ ************************************************/ bool UKUITaskWidget::isApplicationHidden() const { KWindowInfo info(mWindow, NET::WMState); return (info.state() & NET::Hidden); } /************************************************ ************************************************/ bool UKUITaskWidget::isApplicationActive() const { return KWindowSystem::activeWindow() == mWindow; } /************************************************ ************************************************/ void UKUITaskWidget::activateWithDraggable() { // raise app in any time when there is a drag // in progress to allow drop it into an app raiseApplication(); KWindowSystem::forceActiveWindow(mWindow); } /************************************************ ************************************************/ void UKUITaskWidget::raiseApplication() { KWindowSystem::clearState(mWindow, NET::Hidden); if (isWaylandWidget) { QDBusMessage message = QDBusMessage::createSignal("/", "com.ukui.kwin", "request"); QList args; quint32 m_wid=windowId(); args.append(m_wid); args.append(WAYLAND_GROUP_ACTIVATE); repaint(); message.setArguments(args); QDBusConnection::sessionBus().send(message); emit windowMaximize(); setUrgencyHint(false); return; } KWindowInfo info(mWindow, NET::WMDesktop | NET::WMState | NET::XAWMState); if (parentTaskBar()->raiseOnCurrentDesktop() && info.isMinimized()) { KWindowSystem::setOnDesktop(mWindow, KWindowSystem::currentDesktop()); } else { int winDesktop = info.desktop(); if (KWindowSystem::currentDesktop() != winDesktop) KWindowSystem::setCurrentDesktop(winDesktop); } KWindowSystem::activateWindow(mWindow); emit windowMaximize(); setUrgencyHint(false); } /************************************************ ************************************************/ void UKUITaskWidget::minimizeApplication() { KWindowSystem::minimizeWindow(mWindow); } /************************************************ ************************************************/ void UKUITaskWidget::maximizeApplication() { QAction* act = qobject_cast(sender()); if (!act) return; int state = act->data().toInt(); switch (state) { case NET::MaxHoriz: KWindowSystem::setState(mWindow, NET::MaxHoriz); break; case NET::MaxVert: KWindowSystem::setState(mWindow, NET::MaxVert); break; default: KWindowSystem::setState(mWindow, NET::Max); break; } if (!isApplicationActive()) raiseApplication(); } /************************************************ ************************************************/ void UKUITaskWidget::deMaximizeApplication() { KWindowSystem::clearState(mWindow, NET::Max); if (!isApplicationActive()) raiseApplication(); } void UKUITaskWidget::setWindowKeepAbove() { if (!isApplicationActive()) raiseApplication(); KWindowSystem::setState(mWindow, NET::KeepAbove); } void UKUITaskWidget::setWindowStatusClear() { KWindowSystem::clearState(mWindow, NET::KeepAbove); } /************************************************ ************************************************/ void UKUITaskWidget::shadeApplication() { KWindowSystem::setState(mWindow, NET::Shaded); } /************************************************ ************************************************/ void UKUITaskWidget::unShadeApplication() { KWindowSystem::clearState(mWindow, NET::Shaded); } /************************************************ ************************************************/ //void UKUITaskWidget::priv_closeApplication() { //} void UKUITaskWidget::closeApplication() { // FIXME: Why there is no such thing in KWindowSystem?? if (isWaylandWidget) { QDBusMessage message = QDBusMessage::createSignal("/", "com.ukui.kwin", "request"); QList args; quint32 m_wid=windowId(); args.append(m_wid); args.append(WAYLAND_GROUP_CLOSE); message.setArguments(args); QDBusConnection::sessionBus().send(message); } NETRootInfo(QX11Info::connection(), NET::CloseWindow).closeWindowRequest(mWindow); } /************************************************ ************************************************/ void UKUITaskWidget::setApplicationLayer() { QAction* act = qobject_cast(sender()); if (!act) return; int layer = act->data().toInt(); switch(layer) { case NET::KeepAbove: KWindowSystem::clearState(mWindow, NET::KeepBelow); KWindowSystem::setState(mWindow, NET::KeepAbove); break; case NET::KeepBelow: KWindowSystem::clearState(mWindow, NET::KeepAbove); KWindowSystem::setState(mWindow, NET::KeepBelow); break; default: KWindowSystem::clearState(mWindow, NET::KeepBelow); KWindowSystem::clearState(mWindow, NET::KeepAbove); break; } } /************************************************ ************************************************/ void UKUITaskWidget::moveApplicationToDesktop() { QAction* act = qobject_cast(sender()); if (!act) return; bool ok; int desk = act->data().toInt(&ok); if (!ok) return; KWindowSystem::setOnDesktop(mWindow, desk); } /************************************************ ************************************************/ void UKUITaskWidget::moveApplication() { KWindowInfo info(mWindow, NET::WMDesktop); if (!info.isOnCurrentDesktop()) KWindowSystem::setCurrentDesktop(info.desktop()); if (isMinimized()) KWindowSystem::unminimizeWindow(mWindow); KWindowSystem::forceActiveWindow(mWindow); const QRect& g = KWindowInfo(mWindow, NET::WMGeometry).geometry(); int X = g.center().x(); int Y = g.center().y(); QCursor::setPos(X, Y); NETRootInfo(QX11Info::connection(), NET::WMMoveResize).moveResizeRequest(mWindow, X, Y, NET::Move); } /************************************************ ************************************************/ void UKUITaskWidget::resizeApplication() { KWindowInfo info(mWindow, NET::WMDesktop); if (!info.isOnCurrentDesktop()) KWindowSystem::setCurrentDesktop(info.desktop()); if (isMinimized()) KWindowSystem::unminimizeWindow(mWindow); KWindowSystem::forceActiveWindow(mWindow); const QRect& g = KWindowInfo(mWindow, NET::WMGeometry).geometry(); int X = g.bottomRight().x(); int Y = g.bottomRight().y(); QCursor::setPos(X, Y); NETRootInfo(QX11Info::connection(), NET::WMMoveResize).moveResizeRequest(mWindow, X, Y, NET::BottomRight); } /************************************************ ************************************************/ void UKUITaskWidget::setUrgencyHint(bool set) { if (mUrgencyHint == set) return; if (!set) KWindowSystem::demandAttention(mWindow, false); mUrgencyHint = set; setProperty("urgent", set); style()->unpolish(this); style()->polish(this); update(); } /************************************************ ************************************************/ bool UKUITaskWidget::isOnDesktop(int desktop) const { return KWindowInfo(mWindow, NET::WMDesktop).isOnDesktop(desktop); } bool UKUITaskWidget::isOnCurrentScreen() const { return QApplication::desktop()->screenGeometry(parentTaskBar()).intersects(KWindowInfo(mWindow, NET::WMFrameExtents).frameGeometry()); } bool UKUITaskWidget::isMinimized() const { return KWindowInfo(mWindow,NET::WMState | NET::XAWMState).isMinimized(); } bool UKUITaskWidget::isFocusState() const { qDebug()<<"KWindowInfo(mWindow,NET::WMState).state():"<= QT_VERSION_CHECK(5,7,0)) return NET::Focused == (KWindowInfo(mWindow,NET::WMState).state()&NET::Focused); #else return isApplicationActive(); #endif } Qt::Corner UKUITaskWidget::origin() const { return mOrigin; } void UKUITaskWidget::setOrigin(Qt::Corner newOrigin) { if (mOrigin != newOrigin) { mOrigin = newOrigin; update(); } } void UKUITaskWidget::setAutoRotation(bool value, IUKUIPanel::Position position) { if (value) { switch (position) { case IUKUIPanel::PositionTop: case IUKUIPanel::PositionBottom: setOrigin(Qt::TopLeftCorner); break; case IUKUIPanel::PositionLeft: setOrigin(Qt::BottomLeftCorner); break; case IUKUIPanel::PositionRight: setOrigin(Qt::TopRightCorner); break; } } else setOrigin(Qt::TopLeftCorner); } void UKUITaskWidget::paintEvent(QPaintEvent *event) { /*旧的设置预览三态的方式,注释掉的原因是其未能设置阴影*/ #if 0 QStyleOption opt; opt.init(this); QPainter p(this); switch(status) { case NORMAL: { p.setBrush(QBrush(QColor(0x13,0x14,0x14,0xb2))); p.setPen(Qt::black); break; } case HOVER: { // p.setBrush(QBrush(QColor(0xFF,0xFF,0xFF,0x19))); p.setBrush(QBrush(QColor(0x13,0x14,0x14,0x19))); p.setPen(Qt::black); break; } case PRESS: { p.setBrush(QBrush(QColor(0xFF,0xFF,0xFF,0x19))); p.setPen(Qt::white); break; } } p.setRenderHint(QPainter::Antialiasing); // 反锯齿; p.drawRoundedRect(opt.rect,6,6); style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); #endif #if 1 /* * 预览图的设置阴影的方式与其他控件有所不同 * 由于涉及到UKUITaskWidget 中心是一张截图 * 此处设置阴影的方式不是一种通用的方式 * tr: * The way of setting shadow in preview image is different from other controls * As it involves UKUITaskWidget center is a screenshot * The way to set the shadow here is not a general way */ QPainter p(this); p.setRenderHint(QPainter::Antialiasing); QPainterPath rectPath; rectPath.addRoundedRect(this->rect(),6,6); // 画一个黑底 QPixmap pixmap(this->rect().size()); pixmap.fill(Qt::transparent); QPainter pixmapPainter(&pixmap); pixmapPainter.setRenderHint(QPainter::Antialiasing); pixmapPainter.drawPath(rectPath); pixmapPainter.end(); // 模糊这个黑底 extern void qt_blurImage(QImage &blurImage, qreal radius, bool quality, int transposed); QImage img = pixmap.toImage(); qt_blurImage(img, 10, false, false); // 挖掉中心 pixmap = QPixmap::fromImage(img); QPainter pixmapPainter2(&pixmap); pixmapPainter2.setRenderHint(QPainter::Antialiasing); pixmapPainter2.setCompositionMode(QPainter::CompositionMode_Clear); /*在Qt中定义了一个常量,用于设置透明的颜色,即Qt::transparent,表示RGBA值为(0,0,0,0)的透明色。*/ // pixmapPainter2.setPen(Qt::transparent); // pixmapPainter2.setBrush(Qt::transparent); pixmapPainter2.drawPath(rectPath); // 绘制阴影 p.drawPixmap(this->rect(), pixmap, pixmap.rect()); // 绘制底色 p.save(); switch(status) { case NORMAL: { p.fillPath(rectPath, QColor(0x13,0x14,0x14,0xb2)); break; } case HOVER: { p.fillPath(rectPath, QColor(0x13,0x14,0x14,0x66)); break; } case PRESS: { p.fillPath(rectPath, QColor(0xFF,0xFF,0xFF,0x19)); break; } } p.restore(); #endif } bool UKUITaskWidget::hasDragAndDropHover() const { return mDNDTimer->isActive(); } void UKUITaskWidget::updateTitle() { updateText(); } void UKUITaskWidget::setThumbNail(QPixmap _pixmap) { mThumbnailLabel->setPixmap(_pixmap); } void UKUITaskWidget::removeThumbNail() { if(mThumbnailLabel) { mVWindowsLayout->removeWidget(mThumbnailLabel); mThumbnailLabel->setParent(NULL); mThumbnailLabel->deleteLater(); mThumbnailLabel = NULL; } } void UKUITaskWidget::addThumbNail() { if(!mThumbnailLabel) { mThumbnailLabel = new QLabel(this); mThumbnailLabel->setScaledContents(true); mThumbnailLabel->setMinimumSize(QSize(1, 1)); // mVWindowsLayout->addLayout(mTopBarLayout, 100); mVWindowsLayout->addWidget(mThumbnailLabel, 0, Qt::AlignCenter); } else { return; } } void UKUITaskWidget::setTitleFixedWidth(int size) { mTitleLabel->setFixedWidth(size); mTitleLabel->adjustSize(); } int UKUITaskWidget::getWidth() { return mTitleLabel->width(); } void UKUITaskWidget::setThumbFixedSize(int w) { this->mThumbnailLabel->setFixedWidth(w); } void UKUITaskWidget::setThumbMaximumSize(int w) { this->mThumbnailLabel->setMaximumWidth(w); } void UKUITaskWidget::setThumbScale(bool val) { this->mThumbnailLabel->setScaledContents(val); } void UKUITaskWidget::wl_updateIcon(QString iconName){ mAppIcon->setPixmap(QIcon::fromTheme(iconName).pixmap(QSize(19,19))); } void UKUITaskWidget::wl_updateTitle(QString caption) { mTitleLabel->setText(caption); printf("\n%s\n", caption.toStdString().data()); QPalette pa; pa.setColor(QPalette::WindowText,Qt::white); mTitleLabel->setPalette(pa); } ukui-panel-3.0.6.4/plugin-taskbar/quicklaunchaction.cpp0000644000175000017500000001647614204636776021545 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2010-2011 Razor team * Authors: * Petr Vanek * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include #include "quicklaunchaction.h" #include #include #include #include #include #include #include #include #include #include #include "ukuitaskbar.h" #include #include #include #include #include #define USE_STARTUP_INFO false /*用xdg的方式解析*/ QuickLaunchAction::QuickLaunchAction(const XdgDesktopFile * xdg, QWidget * parent) : QAction(parent), m_valid(true) { m_type = ActionXdg; m_settingsMap["desktop"] = xdg->fileName(); QString title(xdg->localizedValue("Name").toString()); QIcon icon=QIcon::fromTheme(xdg->localizedValue("Icon").toString()); //add special path search /use/share/pixmaps if (icon.isNull()) { QString path = QString("/usr/share/pixmaps/%1.%2").arg(xdg->localizedValue("Icon").toString()).arg("png"); QString path_svg = QString("/usr/share/pixmaps/%1.%2").arg(xdg->localizedValue("Icon").toString()).arg("svg"); //qDebug() << "createDesktopFileThumbnail path:" <icon(); setText(title); setIcon(icon); setData(xdg->fileName()); connect(this, &QAction::triggered, this, [this] { execAction(); }); // populate the additional actions for (auto const & action : const_cast(xdg->actions())) { QAction * act = new QAction{xdg->actionIcon(action), xdg->actionName(action), this}; act->setData(action); connect(act, &QAction::triggered, [this, act] { execAction(act->data().toString()); }); m_addtitionalActions.push_back(act); } } #if USE_STARTUP_INFO void pid_callback(GDesktopAppInfo *appinfo, GPid pid, gpointer user_data) { KStartupInfoId* startInfoId = static_cast(user_data); KStartupInfoData data; data.addPid(pid); data.setIconGeometry(QRect(0, 0, 1, 1)); // ugly KStartupInfo::sendChange(*startInfoId, data); KStartupInfo::resetStartupEnv(); g_object_unref(appinfo); delete startInfoId; } #endif /*解析Exec字段*/ void QuickLaunchAction::execAction(QString additionalAction) { UKUITaskBar *uqk = qobject_cast(parent()); QString exec(data().toString()); bool showQMessage = false; switch (m_type) { case ActionLegacy: if (!QProcess::startDetached(exec)) showQMessage =true; break; case ActionXdg: { XdgDesktopFile xdg; if (xdg.load(exec)) { if (additionalAction.isEmpty()) { #if USE_STARTUP_INFO bool needCleanup = true; QWidget * pw = static_cast(parent()); float scale = qApp->devicePixelRatio(); QRect rect = pw->geometry(); rect.moveTo(pw->mapToGlobal(QPoint(0, 0)).x() * scale, pw->mapToGlobal(QPoint(0, 0)).y() * scale); quint32 timeStamp = QX11Info::isPlatformX11() ? QX11Info::appUserTime() : 0; KStartupInfoId* startInfoId = new KStartupInfoId(); startInfoId->initId(KStartupInfo::createNewStartupIdForTimestamp(timeStamp)); startInfoId->setupStartupEnv(); KStartupInfoData data; data.setHostname(); data.setName(exec); data.setIconGeometry(rect); data.setLaunchedBy(getpid()); data.setDescription("Launch by ukui-panel"); KStartupInfo::sendStartup(*startInfoId, data); GDesktopAppInfo * appinfo=g_desktop_app_info_new_from_filename(xdg.fileName().toStdString().data()); needCleanup = !g_desktop_app_info_launch_uris_as_manager(appinfo, nullptr, nullptr, GSpawnFlags::G_SPAWN_DEFAULT, nullptr, nullptr, pid_callback, (gpointer)startInfoId, nullptr); if (needCleanup) { showQMessage =true; delete startInfoId; g_object_unref(appinfo); } #else GDesktopAppInfo * appinfo=g_desktop_app_info_new_from_filename(xdg.fileName().toStdString().data()); if (!g_app_info_launch_uris(G_APP_INFO(appinfo),nullptr, nullptr, nullptr)) showQMessage =true; g_object_unref(appinfo); #endif } else { if (!xdg.actionActivate(additionalAction, QStringList{})) showQMessage =true; } #if 0 } else { //xdg 的方式实现点击打开应用,可正确读取转义的字符 if (additionalAction.isEmpty()){ if (!xdg.startDetached()) showQMessage =true; } else { if (!xdg.actionActivate(additionalAction, QStringList{})) showQMessage =true; } } #endif } else showQMessage =true; } break; case ActionFile: QFileInfo fileinfo(exec); QString openfile = exec; if (fileinfo.isSymLink()) { openfile = fileinfo.symLinkTarget(); } if (fileinfo.exists()) { QDesktopServices::openUrl(QUrl::fromLocalFile(openfile)); } else { showQMessage =true; } break; } if (showQMessage) { qWarning() << "XdgDesktopFile" << exec << "is not valid"; QMessageBox::information(uqk, tr("Error Path"), tr("File/URL cannot be opened cause invalid path.") ); } } QIcon QuickLaunchAction::getIconfromAction() { return this->icon(); } ukui-panel-3.0.6.4/plugin-taskbar/ukuigrouppopup.h0000644000175000017500000000470414203402514020566 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2011 Razor team * 2014 LXQt team * Authors: * Alexander Sokoloff * Maciej Płaza * Kuzma Shapran * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef UKUITASKPOPUP_H #define UKUITASKPOPUP_H #include #include #include #include #include #include "ukuitaskbutton.h" #include "ukuitaskgroup.h" #include "ukuitaskbar.h" class UKUIGroupPopup: public QFrame { Q_OBJECT public: UKUIGroupPopup(UKUITaskGroup *group); ~UKUIGroupPopup(); void hide(bool fast = false); void show(); // Layout int indexOf(UKUITaskButton *button) { return layout()->indexOf(button); } int count() { return layout()->count(); } QLayoutItem * itemAt(int i) { return layout()->itemAt(i); } int spacing() { return layout()->spacing(); } void addButton(UKUITaskButton* button) { layout()->addWidget(button); } void removeWidget(QWidget *button) { layout()->removeWidget(button); } void pubcloseWindowDelay() { closeWindowDelay(); } protected: void dragEnterEvent(QDragEnterEvent * event); void dragLeaveEvent(QDragLeaveEvent *event); void dropEvent(QDropEvent * event); void leaveEvent(QEvent * event); void enterEvent(QEvent * event); void paintEvent(QPaintEvent * event); void mousePressEvent(QMouseEvent *event); void closeTimerSlot(); private: UKUITaskGroup *mGroup; QTimer mCloseTimer; bool rightclick; private slots: void killTimerDelay(); void closeWindowDelay(); }; #endif // UKUITASKPOPUP_H ukui-panel-3.0.6.4/man/0000755000175000017500000000000014204636776013146 5ustar fengfengukui-panel-3.0.6.4/man/panel-daemon.10000644000175000017500000000053114204636776015567 0ustar fengfeng.TH ukui "1" "2020-01-01" "UKUI 0.10.0" "UKUI Desktop Environment" .SH NAME panel-daemon \- Panel background service. .SH SYNOPSIS .B panel-daemon .br .SH DESCRIPTION Monitor the operation of taskbar. .SH BEHAVIOR Monitor the operation of taskbar. .P .SH "REPORTING BUGS" Report bugs to https://github.com/ukui/ukui-panel/issues .SH "SEE ALSO" ukui-panel-3.0.6.4/man/ukui-panel.10000644000175000017500000000216514203402514015262 0ustar fengfeng.TH ukui "1" "2019-08-01" "UKUI 0.10.0" "UKUI Desktop Panel Module" .SH NAME ukui-panel \- The Panel for the UKUI Desktop Environment .SH SYNOPSIS .B ukui-panel .br .SH DESCRIPTION This module adds a panel, with optional plugins, to the desktop. .SH BEHAVIOR The panel can be run independently of \fBUKUI\fR, autostarted at logon, and have multiple instances. A horizontal bottom panel shows by default on the desktop, but the size, autohide, and other attributes .P The panel is comprised of plugins which provide a visual widget; like the startmenu, taskbar, or quicklaunch. They can be added or removed in the panel Widget settings. .P Several plugins are loaded by default; the desktop menu and windows workspaces are also managed here. .SH CONFIGURATIONS Right-click over any plugin to reach the panel Configure settings option, or that of each respective plugin. .SH "REPORTING BUGS" Report bugs to https://github.com/ukui/ukui-panel/issues .SH "SEE ALSO" .SS Ukui Panel documentation can be found under "Help" by right-clicking on \fBukui-panel\fR. Further information may also be available at: http://wiki.ukui-desktop.org/docs .P ukui-panel-3.0.6.4/man/sni-daemon.10000644000175000017500000000075714204636776015273 0ustar fengfeng.TH ukui "1" "2020-01-01" "UKUI 0.10.0" "UKUI Desktop Environment" .SH NAME sni-daemon \- Background service program of SNI protocol. .SH SYNOPSIS .B sni-daemon .br .SH DESCRIPTION sni-daemon monitors the registration behavior of the application and registers it in the system tray. .SH BEHAVIOR sni-daemon monitors the registration behavior of the application and registers it in the system tray. .P .SH "REPORTING BUGS" Report bugs to https://github.com/ukui/ukui-panel/issues .SH "SEE ALSO" ukui-panel-3.0.6.4/man/ukui-flash-disk.10000644000175000017500000000112214203402514016200 0ustar fengfeng.TH ukui "1" "2020-01-01" "UKUI 0.10.0" "UKUI Desktop Environment" .SH NAME ukui-flash-disk \- The Tray Application for the UKUI Desktop Environment .SH SYNOPSIS .B ukui-flash-disk .br .SH DESCRIPTION This is tray application for ukui-panel .SH BEHAVIOR Ukui-flash-disk tray application can detect whether there is external storage medium mounted Click to open the content of the storage medium .P Ukui-flash-disk can according to the detected signal to determine whether to display in the tray bar .SH "REPORTING BUGS" Report bugs to https://github.com/ukui/ukui-panel/issues .SH "SEE ALSO" ukui-panel-3.0.6.4/man/sni-xembed-proxy.10000644000175000017500000000104514204636776016442 0ustar fengfeng.TH ukui "1" "2020-01-01" "UKUI 0.10.0" "UKUI Desktop Environment" .SH NAME sni-xembed-proxy \- Background service program of X to SNI protocol protocol. .SH SYNOPSIS .B sni-xembed-proxy .br .SH DESCRIPTION Convert the tray application registered with X protocol into SNI protocol, and then register it in the system tray. .SH BEHAVIOR Convert the tray application registered with X protocol into SNI protocol, and then register it in the system tray. .P .SH "REPORTING BUGS" Report bugs to https://github.com/ukui/ukui-panel/issues .SH "SEE ALSO" ukui-panel-3.0.6.4/plugin-nightmode/0000755000175000017500000000000014220525730015626 5ustar fengfengukui-panel-3.0.6.4/plugin-nightmode/nightmode.h0000644000175000017500000000611014203402514017746 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include #include #include #include "../panel/ukuipanel.h" #include "../panel/ukuicontrolstyle.h" class NightModeButton:public QToolButton { Q_OBJECT public: /** * @brief NightModeButton * @param plugin * @param parent * 夜间模式按钮 初始化 */ NightModeButton(IUKUIPanelPlugin *plugin, QWidget* parent = 0); ~NightModeButton(); void setupSettings(); protected: void enterEvent(QEvent *); void leaveEvent(QEvent *); void contextMenuEvent(QContextMenuEvent *event); private: void setNightMode(const bool nightMode); void controlCenterSetNightMode(const bool nightMode); void setUkuiStyle(QString ); /** * @brief getNightModeState * 通过dbus获取夜间模式状态 */ void getNightModeState(); IUKUIPanelPlugin * mPlugin; QGSettings *mqtstyleGsettings; QGSettings *mgtkstyleGsettings; QSettings *mqsettings; QSettings * kwinSettings; int colorTemperature; bool mode; public slots: void onClick(); private slots: void nightChangedSlot(QHash nightArg); }; class NightMode : public QObject, public IUKUIPanelPlugin { Q_OBJECT public: /** * @brief NightMode * @param startupInfo * 夜间模式插件,插件上通过添加NightModeButton按钮实现夜间模式相关功能 */ NightMode(const IUKUIPanelPluginStartupInfo &startupInfo); ~NightMode(); virtual QWidget *widget() { return mButton; } virtual QString themeId() const { return QStringLiteral("nightmode"); } void realign(); private: NightModeButton *mButton; QGSettings *gsettings; QTranslator *m_translator; private: void translator(); /** * @brief nightmode_action * 读取配置文件中的nightmode 的值 */ QString nightmode_action; }; class NightModeLibrary: public QObject, public IUKUIPanelPluginLibrary { Q_OBJECT Q_PLUGIN_METADATA(IID "lxqt.org/Panel/PluginInterface/3.0") Q_INTERFACES(IUKUIPanelPluginLibrary) public: IUKUIPanelPlugin *instance(const IUKUIPanelPluginStartupInfo &startupInfo) const { return new NightMode(startupInfo); } }; #endif ukui-panel-3.0.6.4/plugin-nightmode/nightmode.cpp0000644000175000017500000002237514220525730020321 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include #include #include #include "nightmode.h" #include "../panel/customstyle.h" #define UKUI_QT_STYLE "org.ukui.style" #define GTK_STYLE "org.mate.interface" #define UKUI_QT_STYLE_NAME "style-name" #define DEFAULT_QT_STYLE_NAME "styleName" #define GTK_STYLE_NAME "gtk-theme" #define DEFAULT_GTK_STYLE_NAME "gtkTheme" #define DEFAULT_STYLE "ukui-default" #define BLACK_STYLE "ukui-black" #define DARK_STYLE "ukui-dark" #define GTK_WHITE_STYLE "ukui-white" #define UKUI_PANEL_SETTINGS "org.ukui.panel.settings" #define SHOW_NIGHTMODE "shownightmode" NightMode::NightMode(const IUKUIPanelPluginStartupInfo &startupInfo) : QObject(), IUKUIPanelPlugin(startupInfo) { translator(); qDebug()<<"Plugin-NightMode :: plugin-nightmode start"; //读取配置文件中nightmode 的值 QString filename = QDir::homePath() + "/.config/ukui/panel-commission.ini"; QSettings m_settings(filename, QSettings::IniFormat); m_settings.setIniCodec("UTF-8"); m_settings.beginGroup("NightMode"); nightmode_action = m_settings.value("nightmode", "").toString(); if (nightmode_action.isEmpty()) { nightmode_action = "show"; } m_settings.endGroup(); mButton=new NightModeButton(this); mButton->setStyle(new CustomStyle()); const QByteArray id(UKUI_PANEL_SETTINGS); if(QGSettings::isSchemaInstalled(id)) gsettings = new QGSettings(id); connect(gsettings, &QGSettings::changed, this, [=] (const QString &key){ if(key==SHOW_NIGHTMODE) realign(); }); realign(); qDebug()<<"Plugin-NightMode :: plugin-nightmode end"; } NightMode::~NightMode(){ delete gsettings; } void NightMode::translator(){ m_translator = new QTranslator(this); QString locale = QLocale::system().name(); if (locale == "zh_CN"){ if (m_translator->load(QM_INSTALL)) qApp->installTranslator(m_translator); else qDebug() <get(SHOW_NIGHTMODE).toBool() && nightmode_action == "show"){ mButton->setFixedSize(panel()->panelSize()*0.75,panel()->panelSize()); mButton->setIconSize(QSize(panel()->iconSize()*0.75,panel()->iconSize()*0.75)); } else{ mButton->setFixedSize(0,0); mButton->setIconSize(QSize(0,0)); } } NightModeButton::NightModeButton( IUKUIPanelPlugin *plugin, QWidget* parent): QToolButton(parent), mPlugin(plugin) { /*系统主题gsettings qt+gtk*/ const QByteArray styleid(UKUI_QT_STYLE); if(QGSettings::isSchemaInstalled(styleid)) { mqtstyleGsettings = new QGSettings(styleid); } const QByteArray gtkstyleid(GTK_STYLE); if(QGSettings::isSchemaInstalled(gtkstyleid)) { mgtkstyleGsettings = new QGSettings(gtkstyleid); } QDBusInterface iproperty("org.ukui.KWin", "/ColorCorrect", "org.ukui.kwin.ColorCorrect", QDBusConnection::sessionBus()); if (!iproperty.isValid()) { this->setVisible(false); } QDBusConnection::sessionBus().connect(QString(), QString("/ColorCorrect"), "org.ukui.kwin.ColorCorrect", "nightColorConfigChanged", this, SLOT(nightChangedSlot(QHash))); // getNightModeState(); // controlCenterSetNightMode(mode); this->setIcon(QIcon("/usr/share/ukui-panel/panel/img/nightmode-light.svg")); QTimer::singleShot(5000,[this] { this->setToolTip(tr("night mode close")); }); this->setEnabled(false); QTimer *timer = new QTimer(this); connect(timer,&QTimer::timeout,[this] {this->setEnabled(true);}); timer->start(50); connect(this,&NightModeButton::clicked,this, [this] { onClick();}); } NightModeButton::~NightModeButton(){ delete mqtstyleGsettings; delete mgtkstyleGsettings; } void NightModeButton::onClick() { getNightModeState(); if(mode){ setUkuiStyle(DEFAULT_STYLE); }else{ setUkuiStyle(DARK_STYLE); } setNightMode(!mode); this->setEnabled(true); } void NightModeButton::contextMenuEvent(QContextMenuEvent *event) { } /* * 设置夜间模式 * tr: set NightMode */ void NightModeButton::setNightMode(const bool nightMode){ QDBusInterface iproperty("org.ukui.KWin", "/ColorCorrect", "org.ukui.kwin.ColorCorrect", QDBusConnection::sessionBus()); if (!iproperty.isValid()) { this->setVisible(false); return; } QHash data; if(nightMode){ data.insert("Active", true); data.insert("Mode", 3); data.insert("NightTemperature", colorTemperature); iproperty.call("setNightColorConfig", data); QIcon icon=QIcon("/usr/share/ukui-panel/panel/img/nightmode-night.svg"); this->setIcon(icon); this->setToolTip(tr("nightmode opened")); } else{ data.insert("Active", false); iproperty.call("setNightColorConfig", data); this->setIcon(QIcon("/usr/share/ukui-panel/panel/img/nightmode-light.svg")); this->setToolTip(tr("nightmode closed")); } } void NightModeButton::controlCenterSetNightMode(const bool nightMode){ QDBusInterface iproperty("org.ukui.KWin", "/ColorCorrect", "org.ukui.kwin.ColorCorrect", QDBusConnection::sessionBus()); if (!iproperty.isValid()) { this->setVisible(false); return; } QHash data; if(nightMode){ data.insert("Active", true); data.insert("NightTemperature", colorTemperature); iproperty.call("setNightColorConfig", data); QIcon icon=QIcon("/usr/share/ukui-panel/panel/img/nightmode-night.svg"); this->setIcon(icon); QTimer::singleShot(5000,[this] { this->setToolTip(tr("night mode open")); }); } else{ data.insert("Active", false); iproperty.call("setNightColorConfig", data); this->setIcon(QIcon("/usr/share/ukui-panel/panel/img/nightmode-light.svg")); QTimer::singleShot(5000,[this] { this->setToolTip(tr("night mode close")); }); } } void NightModeButton::getNightModeState() { QDBusInterface ipropertyinfo("org.ukui.KWin", "/ColorCorrect", "org.ukui.kwin.ColorCorrect", QDBusConnection::sessionBus()); QDBusMessage msg= ipropertyinfo.call("nightColorInfo"); const QDBusArgument &dbusArg = msg.arguments().at( 0 ).value(); QMap map; dbusArg >> map; for( QString outer_key : map.keys() ){ QVariant innerMap = map.value( outer_key ); if(outer_key=="NightTemperature") colorTemperature=innerMap.toInt(); if(outer_key=="Active") mode=innerMap.toBool(); // if(!outer_key.contains("EveningBeginFixed")) } } void NightModeButton::nightChangedSlot(QHash nightArg) { getNightModeState(); controlCenterSetNightMode(mode); } /*设置主题*/ void NightModeButton::setUkuiStyle(QString style) { if(QString::compare(style,DEFAULT_STYLE)==0){ if(mqtstyleGsettings->keys().contains(DEFAULT_QT_STYLE_NAME) || mqtstyleGsettings->keys().contains(UKUI_QT_STYLE_NAME)) mqtstyleGsettings->set(UKUI_QT_STYLE_NAME,DEFAULT_STYLE); if(mgtkstyleGsettings->keys().contains(DEFAULT_GTK_STYLE_NAME) || mgtkstyleGsettings->keys().contains(GTK_STYLE_NAME)) mgtkstyleGsettings->set(GTK_STYLE_NAME,GTK_WHITE_STYLE); } else{ if(mqtstyleGsettings->keys().contains(DEFAULT_QT_STYLE_NAME) || mqtstyleGsettings->keys().contains(UKUI_QT_STYLE_NAME)) mqtstyleGsettings->set(UKUI_QT_STYLE_NAME,DARK_STYLE); if(mgtkstyleGsettings->keys().contains(DEFAULT_GTK_STYLE_NAME) || mgtkstyleGsettings->keys().contains(GTK_STYLE_NAME)) mgtkstyleGsettings->set(GTK_STYLE_NAME,BLACK_STYLE); } } void NightModeButton::enterEvent(QEvent *) { repaint(); return; } void NightModeButton::leaveEvent(QEvent *) { repaint(); return; } ukui-panel-3.0.6.4/plugin-nightmode/resources/0000755000175000017500000000000014203402514017633 5ustar fengfengukui-panel-3.0.6.4/plugin-nightmode/resources/nightmode.desktop.in0000644000175000017500000000030114203402514023603 0ustar fengfeng[Desktop Entry] Type=Service ServiceTypes=UKUIPanel/Plugin Name=NightMode Comment=NightMode Icon=nightmode #TRANSLATIONS_DIR=../translations Name=夜间模式 Comment=夜间模式切换按键 ukui-panel-3.0.6.4/plugin-nightmode/CMakeLists.txt0000644000175000017500000000046414203402514020365 0ustar fengfengset(PLUGIN "nightmode") set(HEADERS nightmode.h ) set(SOURCES nightmode.cpp ) set(LIBRARIES # Qt5Xdg ${Gsetting_LIBRARIES} ) include(../cmake/UkuiPluginTranslationTs.cmake) ukui_plugin_translate_ts(${PLUGIN}) include_directories(${_Qt5DBus_OWN_INCLUDE_DIRS}) BUILD_UKUI_PLUGIN(${PLUGIN}) ukui-panel-3.0.6.4/plugin-nightmode/translation/0000755000175000017500000000000014203402514020157 5ustar fengfengukui-panel-3.0.6.4/plugin-nightmode/translation/nightmode_zh_CN.ts0000644000175000017500000000230414203402514023565 0ustar fengfeng NightModeButton Turn On NightMode 夜间模式 Set Up NightMode 设置夜间模式 nightmode opened 夜间模式开启 nightmode closed 夜间模式关闭 night mode open 夜间模式开启 night mode close 夜间模式关闭 ukui-panel-3.0.6.4/sni-xembed-proxy/0000755000175000017500000000000014203402514015561 5ustar fengfengukui-panel-3.0.6.4/sni-xembed-proxy/kf5_org.kde.StatusNotifierWatcher.xml0000644000175000017500000000217714203402514024710 0ustar fengfeng ukui-panel-3.0.6.4/sni-xembed-proxy/snixembedproxy.h0000644000175000017500000000320514203402514021012 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include class KSelectionOwner; class SNIProxy; class SniXembedProxy : public QObject,public QAbstractNativeEventFilter { Q_OBJECT public: SniXembedProxy(); ~SniXembedProxy(); protected: bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) override; private: void init(); bool addDamageWatch(xcb_window_t client); void dock(xcb_window_t embed_win); void undock(xcb_window_t client); void setSystemTrayVisual(); private Q_SLOTS: void onClaimedOwnership(); void onFailedToClaimOwnership(); void onLostOwnership(); private: uint8_t m_damageEventBase; QHash m_damageWatches; QHash m_proxies; KSelectionOwner *m_selectionOwner; }; #endif // SNIXEMBEDPROXY_H ukui-panel-3.0.6.4/sni-xembed-proxy/snidbus.cpp0000755000175000017500000000765114203402514017750 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include //mostly copied from KStatusNotiferItemDbus.cpps from knotification KDbusImageStruct::KDbusImageStruct() { } KDbusImageStruct::KDbusImageStruct(const QImage &image) { width = image.size().width(); height = image.size().height(); if (image.format() == QImage::Format_ARGB32) { data = QByteArray((char *)image.bits(), image.byteCount()); } else { QImage image32 = image.convertToFormat(QImage::Format_ARGB32); data = QByteArray((char *)image32.bits(), image32.byteCount()); } //swap to network byte order if we are little endian if (QSysInfo::ByteOrder == QSysInfo::LittleEndian) { quint32 *uintBuf = (quint32 *) data.data(); for (uint i = 0; i < data.size() / sizeof(quint32); ++i) { *uintBuf = qToBigEndian(*uintBuf); ++uintBuf; } } } // Marshall the ImageStruct data into a D-BUS argument const QDBusArgument &operator<<(QDBusArgument &argument, const KDbusImageStruct &icon) { argument.beginStructure(); argument << icon.width; argument << icon.height; argument << icon.data; argument.endStructure(); return argument; } // Retrieve the ImageStruct data from the D-BUS argument const QDBusArgument &operator>>(const QDBusArgument &argument, KDbusImageStruct &icon) { qint32 width; qint32 height; QByteArray data; argument.beginStructure(); argument >> width; argument >> height; argument >> data; argument.endStructure(); icon.width = width; icon.height = height; icon.data = data; return argument; } // Marshall the ImageVector data into a D-BUS argument const QDBusArgument &operator<<(QDBusArgument &argument, const KDbusImageVector &iconVector) { argument.beginArray(qMetaTypeId()); for (int i = 0; i < iconVector.size(); ++i) { argument << iconVector[i]; } argument.endArray(); return argument; } // Retrieve the ImageVector data from the D-BUS argument const QDBusArgument &operator>>(const QDBusArgument &argument, KDbusImageVector &iconVector) { argument.beginArray(); iconVector.clear(); while (!argument.atEnd()) { KDbusImageStruct element; argument >> element; iconVector.append(element); } argument.endArray(); return argument; } // Marshall the ToolTipStruct data into a D-BUS argument const QDBusArgument &operator<<(QDBusArgument &argument, const KDbusToolTipStruct &toolTip) { argument.beginStructure(); argument << toolTip.icon; argument << toolTip.image; argument << toolTip.title; argument << toolTip.subTitle; argument.endStructure(); return argument; } // Retrieve the ToolTipStruct data from the D-BUS argument const QDBusArgument &operator>>(const QDBusArgument &argument, KDbusToolTipStruct &toolTip) { QString icon; KDbusImageVector image; QString title; QString subTitle; argument.beginStructure(); argument >> icon; argument >> image; argument >> title; argument >> subTitle; argument.endStructure(); toolTip.icon = icon; toolTip.image = image; toolTip.title = title; toolTip.subTitle = subTitle; return argument; } ukui-panel-3.0.6.4/sni-xembed-proxy/org.freedesktop.DBus.Properties.xml0000755000175000017500000000207514203402514024402 0ustar fengfeng ukui-panel-3.0.6.4/sni-xembed-proxy/snixembedproxy.cpp0000644000175000017500000002102314203402514021343 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include #include #include #include #include "xcbutilss.h" #include "sniproxy.h" #define SYSTEM_TRAY_REQUEST_DOCK 0 #define SYSTEM_TRAY_BEGIN_MESSAGE 1 #define SYSTEM_TRAY_CANCEL_MESSAGE 2 SniXembedProxy::SniXembedProxy() { m_selectionOwner = new KSelectionOwner(Xcb::atoms->selectionAtom, -1, this); QTimer::singleShot(0, this, &SniXembedProxy::init); } SniXembedProxy::~SniXembedProxy() { } void SniXembedProxy::init() { //load damage extension xcb_connection_t *c = QX11Info::connection(); xcb_prefetch_extension_data(c, &xcb_damage_id); const auto *reply = xcb_get_extension_data(c, &xcb_damage_id); if (reply && reply->present) { m_damageEventBase = reply->first_event; xcb_damage_query_version_unchecked(c, XCB_DAMAGE_MAJOR_VERSION, XCB_DAMAGE_MINOR_VERSION); } else { //no XDamage means qDebug() << "could not load damage extension. Quitting"; qApp->exit(-1); } qApp->installNativeEventFilter(this); connect(m_selectionOwner, &KSelectionOwner::claimedOwnership, this, &SniXembedProxy::onClaimedOwnership); connect(m_selectionOwner, &KSelectionOwner::failedToClaimOwnership, this, &SniXembedProxy::onFailedToClaimOwnership); connect(m_selectionOwner, &KSelectionOwner::lostOwnership, this, &SniXembedProxy::onLostOwnership); m_selectionOwner->claim(false); } bool SniXembedProxy::nativeEventFilter(const QByteArray &eventType, void *message, long int *result) { Q_UNUSED(result) if (eventType != "xcb_generic_event_t") { return false; } xcb_generic_event_t *ev = static_cast(message); const auto responseType = XCB_EVENT_RESPONSE_TYPE(ev); if (responseType == XCB_CLIENT_MESSAGE) { const auto ce = reinterpret_cast(ev); if (ce->type == Xcb::atoms->opcodeAtom) { switch (ce->data.data32[1]) { case SYSTEM_TRAY_REQUEST_DOCK: dock(ce->data.data32[2]); return true; } } } else if (responseType == XCB_UNMAP_NOTIFY) { const auto unmappedWId = reinterpret_cast(ev)->window; if (m_proxies.contains(unmappedWId)) { undock(unmappedWId); } } else if (responseType == XCB_DESTROY_NOTIFY) { const auto destroyedWId = reinterpret_cast(ev)->window; if (m_proxies.contains(destroyedWId)) { undock(destroyedWId); } } else if (responseType == m_damageEventBase + XCB_DAMAGE_NOTIFY) { const auto damagedWId = reinterpret_cast(ev)->drawable; const auto sniProxy = m_proxies.value(damagedWId); if (sniProxy) { sniProxy->update(); xcb_damage_subtract(QX11Info::connection(), m_damageWatches[damagedWId], XCB_NONE, XCB_NONE); } } else if (responseType == XCB_CONFIGURE_REQUEST) { const auto event = reinterpret_cast(ev); const auto sniProxy = m_proxies.value(event->window); if (sniProxy) { // The embedded window tries to move or resize. Ignore move, handle resize only. if ((event->value_mask & XCB_CONFIG_WINDOW_WIDTH) || (event->value_mask & XCB_CONFIG_WINDOW_HEIGHT)) { sniProxy->resizeWindow(event->width, event->height); } } } else if (responseType == XCB_VISIBILITY_NOTIFY) { const auto event = reinterpret_cast(ev); // it's possible that something showed our container window, we have to hide it // workaround for BUG 357443: when KWin is restarted, container window is shown on top if (event->state == XCB_VISIBILITY_UNOBSCURED) { for (auto sniProxy : m_proxies.values()) { sniProxy->hideContainerWindow(event->window); } } } return false; } void SniXembedProxy::dock(xcb_window_t winId) { qDebug() << "trying to dock window " << winId; if (m_proxies.contains(winId)) { return; } if (addDamageWatch(winId)) { m_proxies[winId] = new SNIProxy(winId, this); } } void SniXembedProxy::undock(xcb_window_t winId) { qDebug() << "trying to undock window " << winId; if (!m_proxies.contains(winId)) { return; } m_proxies[winId]->deleteLater(); m_proxies.remove(winId); } bool SniXembedProxy::addDamageWatch(xcb_window_t client) { qDebug() << "adding damage watch for " << client; xcb_connection_t *c = QX11Info::connection(); const auto attribsCookie = xcb_get_window_attributes_unchecked(c, client); const auto damageId = xcb_generate_id(c); m_damageWatches[client] = damageId; xcb_damage_create(c, damageId, client, XCB_DAMAGE_REPORT_LEVEL_NON_EMPTY); xcb_generic_error_t *error = nullptr; QScopedPointer attr(xcb_get_window_attributes_reply(c, attribsCookie, &error)); QScopedPointer getAttrError(error); uint32_t events = XCB_EVENT_MASK_STRUCTURE_NOTIFY; if (!attr.isNull()) { events = events | attr->your_event_mask; } // if window is already gone, there is no need to handle it. if (getAttrError && getAttrError->error_code == XCB_WINDOW) { return false; } // the event mask will not be removed again. We cannot track whether another component also needs STRUCTURE_NOTIFY (e.g. KWindowSystem). // if we would remove the event mask again, other areas will break. const auto changeAttrCookie = xcb_change_window_attributes_checked(c, client, XCB_CW_EVENT_MASK, &events); QScopedPointer changeAttrError(xcb_request_check(c, changeAttrCookie)); // if window is gone by this point, it will be caught by eventFilter, so no need to check later errors. if (changeAttrError && changeAttrError->error_code == XCB_WINDOW) { return false; } return true; } void SniXembedProxy::onClaimedOwnership() { qDebug() << "Manager selection claimed"; setSystemTrayVisual(); } void SniXembedProxy::onFailedToClaimOwnership() { qWarning() << "failed to claim ownership of Systray Manager"; qApp->exit(-1); } void SniXembedProxy::onLostOwnership() { qWarning() << "lost ownership of Systray Manager"; qApp->exit(-1); } void SniXembedProxy::setSystemTrayVisual() { xcb_connection_t *c = QX11Info::connection(); auto screen = xcb_setup_roots_iterator(xcb_get_setup(c)).data; auto trayVisual = screen->root_visual; xcb_depth_iterator_t depth_iterator = xcb_screen_allowed_depths_iterator(screen); xcb_depth_t *depth = nullptr; while (depth_iterator.rem) { if (depth_iterator.data->depth == 32) { depth = depth_iterator.data; break; } xcb_depth_next(&depth_iterator); } if (depth) { xcb_visualtype_iterator_t visualtype_iterator = xcb_depth_visuals_iterator(depth); while (visualtype_iterator.rem) { xcb_visualtype_t *visualtype = visualtype_iterator.data; if (visualtype->_class == XCB_VISUAL_CLASS_TRUE_COLOR) { trayVisual = visualtype->visual_id; break; } xcb_visualtype_next(&visualtype_iterator); } } xcb_change_property(c, XCB_PROP_MODE_REPLACE, m_selectionOwner->ownerWindow(), Xcb::atoms->visualAtom, XCB_ATOM_VISUALID, 32, 1, &trayVisual); } ukui-panel-3.0.6.4/sni-xembed-proxy/statusnotifierwatcher_interface.cpp0000644000175000017500000000161214203402514024746 0ustar fengfeng/* * This file was generated by qdbusxml2cpp version 0.8 * Command line was: qdbusxml2cpp -m -c OrgKdeStatusNotifierWatcherInterface -i systemtraytypedefs.h -p statusnotifierwatcher_interface kf5_org.kde.StatusNotifierWatcher.xml * * qdbusxml2cpp is Copyright (C) 2020 The Qt Company Ltd. * * This is an auto-generated file. * This file may have been hand-edited. Look for HAND-EDIT comments * before re-generating it. */ #include "statusnotifierwatcher_interface.h" /* * Implementation of interface class OrgKdeStatusNotifierWatcherInterface */ OrgKdeStatusNotifierWatcherInterface::OrgKdeStatusNotifierWatcherInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent) : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent) { } OrgKdeStatusNotifierWatcherInterface::~OrgKdeStatusNotifierWatcherInterface() { } ukui-panel-3.0.6.4/sni-xembed-proxy/snidbus.h0000755000175000017500000000411214203402514017402 0ustar fengfeng/* * SNI Dbus serialisers * Copyright 2015 David Edmundson * * 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) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * 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, see . * */ #ifndef SNIDBUS_H #define SNIDBUS_H #include #include #include #include #include //Custom message type for DBus struct KDbusImageStruct { KDbusImageStruct(); KDbusImageStruct(const QImage &image); int width; int height; QByteArray data; }; typedef QVector KDbusImageVector; struct KDbusToolTipStruct { QString icon; KDbusImageVector image; QString title; QString subTitle; }; const QDBusArgument &operator<<(QDBusArgument &argument, const KDbusImageStruct &icon); const QDBusArgument &operator>>(const QDBusArgument &argument, KDbusImageStruct &icon); Q_DECLARE_METATYPE(KDbusImageStruct) const QDBusArgument &operator<<(QDBusArgument &argument, const KDbusImageVector &iconVector); const QDBusArgument &operator>>(const QDBusArgument &argument, KDbusImageVector &iconVector); Q_DECLARE_METATYPE(KDbusImageVector) const QDBusArgument &operator<<(QDBusArgument &argument, const KDbusToolTipStruct &toolTip); const QDBusArgument &operator>>(const QDBusArgument &argument, KDbusToolTipStruct &toolTip); Q_DECLARE_METATYPE(KDbusToolTipStruct) #endif // SNIDBUS_H ukui-panel-3.0.6.4/sni-xembed-proxy/sniproxy.cpp0000755000175000017500000005501214203402514020166 0ustar fengfeng/* * Holds one embedded window, registers as DBus entry * Copyright (C) 2015 David Edmundson * Copyright (C) 2019 Konrad Materka * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * */ #include "sniproxy.h" #include #include #include #include #include #include #include "xcbutilss.h" #include #include #include #include #include #include #include #include #include #include #include #include //#include "statusnotifieritemadaptor.h" #include "statusnotifierwatcher_interface.h" //#define VISUAL_DEBUG #define SNI_WATCHER_SERVICE_NAME "org.kde.StatusNotifierWatcher" #define SNI_WATCHER_PATH "/StatusNotifierWatcher" static uint16_t s_embedSize = 32; //max size of window to embed. We no longer resize the embedded window as Chromium acts stupidly. static unsigned int XEMBED_VERSION = 0; int SNIProxy::s_serviceCount = 0; void xembed_message_send(xcb_window_t towin, long message, long d1, long d2, long d3) { xcb_client_message_event_t ev; ev.response_type = XCB_CLIENT_MESSAGE; ev.window = towin; ev.format = 32; ev.data.data32[0] = XCB_CURRENT_TIME; ev.data.data32[1] = message; ev.data.data32[2] = d1; ev.data.data32[3] = d2; ev.data.data32[4] = d3; ev.type = Xcb::atoms->xembedAtom; xcb_send_event(QX11Info::connection(), false, towin, XCB_EVENT_MASK_NO_EVENT, (char *) &ev); } SNIProxy::SNIProxy(xcb_window_t wid, QObject* parent): QObject(parent), //Work round a bug in our SNIWatcher with multiple SNIs per connection. //there is an undocumented feature that you can register an SNI by path, however it doesn't detect an object on a service being removed, only the entire service closing //instead lets use one DBus connection per SNI m_dbus(QDBusConnection::connectToBus(QDBusConnection::SessionBus, QStringLiteral("XembedSniProxy%1").arg(s_serviceCount++))), m_windowId(wid), sendingClickEvent(false), m_injectMode(Direct) { //create new SNI qRegisterMetaType("KDbusImageStruct"); qDBusRegisterMetaType(); qRegisterMetaType("KDbusImageVector"); qDBusRegisterMetaType(); m_dbus.registerObject(QStringLiteral("/StatusNotifierItem"), this,QDBusConnection::ExportAllContents); auto statusNotifierWatcher = new org::kde::StatusNotifierWatcher(QStringLiteral(SNI_WATCHER_SERVICE_NAME), QStringLiteral(SNI_WATCHER_PATH), QDBusConnection::sessionBus(), this); qDebug()<<"sni-proxy:RegisterStatusNotifierItem = " <RegisterStatusNotifierItem(m_dbus.baseService()); reply.waitForFinished(); if (reply.isError()) { qWarning() << "could not register SNI:" << reply.error().message(); } auto c = QX11Info::connection(); //create a container window auto screen = xcb_setup_roots_iterator (xcb_get_setup (c)).data; m_containerWid = xcb_generate_id(c); uint32_t values[3]; uint32_t mask = XCB_CW_BACK_PIXEL | XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK; values[0] = screen->black_pixel; //draw a solid background so the embedded icon doesn't get garbage in it values[1] = true; //bypass wM values[2] = XCB_EVENT_MASK_VISIBILITY_CHANGE | // receive visibility change, to handle KWin restart #357443 // Redirect and handle structure (size, position) requests from the embedded window. XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT; xcb_create_window (c, /* connection */ XCB_COPY_FROM_PARENT, /* depth */ m_containerWid, /* window Id */ screen->root, /* parent window */ 0, 0, /* x, y */ s_embedSize, s_embedSize, /* width, height */ 0, /* border_width */ XCB_WINDOW_CLASS_INPUT_OUTPUT,/* class */ screen->root_visual, /* visual */ mask, values); /* masks */ /* We need the window to exist and be mapped otherwise the child won't render it's contents We also need it to exist in the right place to get the clicks working as GTK will check sendEvent locations to see if our window is in the right place. So even though our contents are drawn via compositing we still put this window in the right place We can't composite it away anything parented owned by the root window (apparently) Stack Under works in the non composited case, but it doesn't seem to work in kwin's composited case (probably need set relevant NETWM hint) As a last resort set opacity to 0 just to make sure this container never appears */ #ifndef VISUAL_DEBUG stackContainerWindow(XCB_STACK_MODE_BELOW); NETWinInfo wm(c, m_containerWid, screen->root, NET::Properties(), NET::Properties2()); wm.setOpacity(0); #endif xcb_flush(c); xcb_map_window(c, m_containerWid); xcb_reparent_window(c, wid, m_containerWid, 0, 0); /* * Render the embedded window offscreen */ xcb_composite_redirect_window(c, wid, XCB_COMPOSITE_REDIRECT_MANUAL); /* we grab the window, but also make sure it's automatically reparented back * to the root window if we should die. */ xcb_change_save_set(c, XCB_SET_MODE_INSERT, wid); //tell client we're embedding it xembed_message_send(wid, XEMBED_EMBEDDED_NOTIFY, 0, m_containerWid, XEMBED_VERSION); //move window we're embedding const uint32_t windowMoveConfigVals[2] = { 0, 0 }; xcb_configure_window(c, wid, XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y, windowMoveConfigVals); QSize clientWindowSize = calculateClientWindowSize(); //show the embedded window otherwise nothing happens xcb_map_window(c, wid); xcb_clear_area(c, 0, wid, 0, 0, clientWindowSize.width(), clientWindowSize.height()); xcb_flush(c); //guess which input injection method to use //we can either send an X event to the client or XTest //some don't support direct X events (GTK3/4), and some don't support XTest because reasons //note also some clients might not have the XTest extension. We may as well assume it does and just fail to send later. //we query if the client selected button presses in the event mask //if the client does supports that we send directly, otherwise we'll use xtest auto waCookie = xcb_get_window_attributes(c, wid); QScopedPointer windowAttributes(xcb_get_window_attributes_reply(c, waCookie, nullptr)); if (windowAttributes && ! (windowAttributes->all_event_masks & XCB_EVENT_MASK_BUTTON_PRESS)) { m_injectMode = XTest; } //there's no damage event for the first paint, and sometimes it's not drawn immediately //not ideal, but it works better than nothing //test with xchat before changing QTimer::singleShot(500, this, &SNIProxy::update); } SNIProxy::~SNIProxy() { auto c = QX11Info::connection(); xcb_destroy_window(c, m_containerWid); QDBusConnection::disconnectFromBus(m_dbus.name()); } void SNIProxy::update() { const QImage image = getImageNonComposite(); if (image.isNull()) { qDebug() << "No xembed icon for" << m_windowId << Title(); return; } int w = image.width(); int h = image.height(); m_pixmap = QPixmap::fromImage(image); if (w > s_embedSize || h > s_embedSize) { qDebug() << "Scaling pixmap of window" << m_windowId << Title() << "from w*h" << w << h; m_pixmap = m_pixmap.scaled(s_embedSize, s_embedSize, Qt::KeepAspectRatio, Qt::SmoothTransformation); } Q_EMIT NewIcon(); Q_EMIT NewToolTip(); } void SNIProxy::resizeWindow(const uint16_t width, const uint16_t height) const { auto connection = QX11Info::connection(); uint16_t widthNormalized = std::min(width, s_embedSize); uint16_t heighNormalized = std::min(height, s_embedSize); const uint32_t windowSizeConfigVals[2] = { widthNormalized, heighNormalized }; xcb_configure_window(connection, m_windowId, XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT, windowSizeConfigVals); xcb_flush(connection); } void SNIProxy::hideContainerWindow(xcb_window_t windowId) const { if (m_containerWid == windowId && !sendingClickEvent) { qDebug() << "Container window visible, stack below"; stackContainerWindow(XCB_STACK_MODE_BELOW); } } QSize SNIProxy::calculateClientWindowSize() const { auto c = QX11Info::connection(); auto cookie = xcb_get_geometry(c, m_windowId); QScopedPointer clientGeom(xcb_get_geometry_reply(c, cookie, nullptr)); QSize clientWindowSize; if (clientGeom) { clientWindowSize = QSize(clientGeom->width, clientGeom->height); } //if the window is a clearly stupid size resize to be something sensible //this is needed as chromium and such when resized just fill the icon with transparent space and only draw in the middle //however KeePass2 does need this as by default the window size is 273px wide and is not transparent //use an artbitrary heuristic to make sure icons are always sensible if (clientWindowSize.isEmpty() || clientWindowSize.width() > s_embedSize || clientWindowSize.height() > s_embedSize) { qDebug() << "Resizing window" << m_windowId << Title() << "from w*h" << clientWindowSize; resizeWindow(s_embedSize, s_embedSize); clientWindowSize = QSize(s_embedSize, s_embedSize); } return clientWindowSize; } void sni_cleanup_xcb_image(void *data) { xcb_image_destroy(static_cast(data)); } bool SNIProxy::isTransparentImage(const QImage& image) const { int w = image.width(); int h = image.height(); // check for the center and sub-center pixels first and avoid full image scan if (! (qAlpha(image.pixel(w >> 1, h >> 1)) + qAlpha(image.pixel(w >> 2, h >> 2)) == 0)) return false; // skip scan altogether if sub-center pixel found to be opaque // and break out from the outer loop too on full scan for (int x = 0; x < w; ++x) { for (int y = 0; y < h; ++y) { if (qAlpha(image.pixel(x, y))) { // Found an opaque pixel. return false; } } } return true; } QImage SNIProxy::getImageNonComposite() const { auto c = QX11Info::connection(); QSize clientWindowSize = calculateClientWindowSize(); xcb_image_t *image = xcb_image_get(c, m_windowId, 0, 0, clientWindowSize.width(), clientWindowSize.height(), 0xFFFFFFFF, XCB_IMAGE_FORMAT_Z_PIXMAP); // Don't hook up cleanup yet, we may use a different QImage after all QImage naiveConversion; if (image) { naiveConversion = QImage(image->data, image->width, image->height, QImage::Format_ARGB32); } else { qDebug() << "Skip NULL image returned from xcb_image_get() for" << m_windowId << Title(); return QImage(); } if (isTransparentImage(naiveConversion)) { QImage elaborateConversion = QImage(convertFromNative(image)); // Update icon only if it is at least partially opaque. // This is just a workaround for X11 bug: xembed icon may suddenly // become transparent for a one or few frames. Reproducible at least // with WINE applications. if (isTransparentImage(elaborateConversion)) { qDebug() << "Skip transparent xembed icon for" << m_windowId << Title(); return QImage(); } else return elaborateConversion; } else { // Now we are sure we can eventually delete the xcb_image_t with this version return QImage(image->data, image->width, image->height, image->stride, QImage::Format_ARGB32, sni_cleanup_xcb_image, image); } } QImage SNIProxy::convertFromNative(xcb_image_t *xcbImage) const { QImage::Format format = QImage::Format_Invalid; switch (xcbImage->depth) { case 1: format = QImage::Format_MonoLSB; break; case 16: format = QImage::Format_RGB16; break; case 24: format = QImage::Format_RGB32; break; case 30: { // Qt doesn't have a matching image format. We need to convert manually quint32 *pixels = reinterpret_cast(xcbImage->data); for (uint i = 0; i < (xcbImage->size / 4); i++) { int r = (pixels[i] >> 22) & 0xff; int g = (pixels[i] >> 12) & 0xff; int b = (pixels[i] >> 2) & 0xff; pixels[i] = qRgba(r, g, b, 0xff); } // fall through, Qt format is still Format_ARGB32_Premultiplied Q_FALLTHROUGH(); } case 32: format = QImage::Format_ARGB32_Premultiplied; break; default: return QImage(); // we don't know } QImage image(xcbImage->data, xcbImage->width, xcbImage->height, xcbImage->stride, format, sni_cleanup_xcb_image, xcbImage); if (image.isNull()) { return QImage(); } if (format == QImage::Format_RGB32 && xcbImage->bpp == 32) { QImage m = image.createHeuristicMask(); QBitmap mask(QPixmap::fromImage(m)); QPixmap p = QPixmap::fromImage(image); p.setMask(mask); image = p.toImage(); } // work around an abort in QImage::color if (image.format() == QImage::Format_MonoLSB) { image.setColorCount(2); image.setColor(0, QColor(Qt::white).rgb()); image.setColor(1, QColor(Qt::black).rgb()); } return image; } /* Wine is using XWindow Shape Extension for transparent tray icons. We need to find first clickable point starting from top-left. */ QPoint SNIProxy::calculateClickPoint() const { QPoint clickPoint = QPoint(0, 0); auto c = QX11Info::connection(); // request extent to check if shape has been set xcb_shape_query_extents_cookie_t extentsCookie = xcb_shape_query_extents(c, m_windowId); // at the same time make the request for rectangles (even if this request isn't needed) xcb_shape_get_rectangles_cookie_t rectaglesCookie = xcb_shape_get_rectangles(c, m_windowId, XCB_SHAPE_SK_BOUNDING); QScopedPointer extentsReply(xcb_shape_query_extents_reply(c, extentsCookie, nullptr)); QScopedPointer rectanglesReply(xcb_shape_get_rectangles_reply(c, rectaglesCookie, nullptr)); if (!extentsReply || !rectanglesReply || !extentsReply->bounding_shaped) { return clickPoint; } xcb_rectangle_t *rectangles = xcb_shape_get_rectangles_rectangles(rectanglesReply.get()); if (!rectangles) { return clickPoint; } const QImage image = getImageNonComposite(); double minLength = sqrt(pow(image.height(), 2) + pow(image.width(), 2)); const int nRectangles = xcb_shape_get_rectangles_rectangles_length(rectanglesReply.get()); for (int i = 0; i < nRectangles; ++i) { double length = sqrt(pow(rectangles[i].x, 2) + pow(rectangles[i].y, 2)); if (length < minLength) { minLength = length; clickPoint = QPoint(rectangles[i].x, rectangles[i].y); } } qDebug() << "Click point:" << clickPoint; return clickPoint; } void SNIProxy::stackContainerWindow(const uint32_t stackMode) const { auto c = QX11Info::connection(); const uint32_t stackData[] = {stackMode}; xcb_configure_window(c, m_containerWid, XCB_CONFIG_WINDOW_STACK_MODE, stackData); } //____________properties__________ QString SNIProxy::Category() const { return QStringLiteral("ApplicationStatus"); } QString SNIProxy::Id() const { KWindowInfo window (m_windowId, NET::WMName,NET::WM2WindowClass); const auto title = window.windowClassClass(); //we always need /some/ ID so if no window title exists, just use the winId. if (title.isEmpty()) { return QString::number(m_windowId); } return title; } KDbusImageVector SNIProxy::IconPixmap() const { KDbusImageStruct dbusImage(m_pixmap.toImage()); return KDbusImageVector() << dbusImage; } bool SNIProxy::ItemIsMenu() const { return false; } QString SNIProxy::Status() const { return QStringLiteral("Active"); } QString SNIProxy::Title() const { KWindowInfo window (m_windowId, NET::WMName,NET::WM2WindowClass); //根据应用的dekstop文件查找中文名 QString toolTip; ConvertDesktopToWinId *getDesktop = new ConvertDesktopToWinId(); QString appDesktopPath = getDesktop->tranIdToDesktop(window.win()); delete getDesktop; if(QFile::exists(appDesktopPath)){ XdgDesktopFile xdg; xdg.load(appDesktopPath); toolTip = xdg.localizedValue("Name").toString(); if(!toolTip.isEmpty()){ return toolTip; } } toolTip = QString(window.windowClassClass()); return toolTip; } int SNIProxy::WindowId() const { return m_windowId; } //____________actions_____________ void SNIProxy::Activate(int x, int y) { sendClick(XCB_BUTTON_INDEX_1, x, y); } void SNIProxy::SecondaryActivate(int x, int y) { sendClick(XCB_BUTTON_INDEX_2, x, y); } void SNIProxy::ContextMenu(int x, int y) { sendClick(XCB_BUTTON_INDEX_3, x, y); } void SNIProxy::Scroll(int delta, const QString& orientation) { if (orientation == QLatin1String("vertical")) { sendClick(delta > 0 ? XCB_BUTTON_INDEX_4: XCB_BUTTON_INDEX_5, 0, 0); } else { sendClick(delta > 0 ? 6: 7, 0, 0); } } void SNIProxy::sendClick(uint8_t mouseButton, int x, int y) { //it's best not to look at this code //GTK doesn't like send_events and double checks the mouse position matches where the window is and is top level //in order to solve this we move the embed container over to where the mouse is then replay the event using send_event //if patching, test with xchat + xchat context menus //note x,y are not actually where the mouse is, but the plasmoid //ideally we should make this match the plasmoid hit area qDebug() << "Received click" << mouseButton << "with passed x*y" << x << y; sendingClickEvent = true; auto c = QX11Info::connection(); auto cookieSize = xcb_get_geometry(c, m_windowId); QScopedPointer clientGeom(xcb_get_geometry_reply(c, cookieSize, nullptr)); if (!clientGeom) { return; } auto cookie = xcb_query_pointer(c, m_windowId); QScopedPointer pointer(xcb_query_pointer_reply(c, cookie, nullptr)); /*qCDebug(SNIPROXY) << "samescreen" << pointer->same_screen << endl << "root x*y" << pointer->root_x << pointer->root_y << endl << "win x*y" << pointer->win_x << pointer->win_y;*/ //move our window so the mouse is within its geometry uint32_t configVals[2] = {0, 0}; const QPoint clickPoint = calculateClickPoint(); if (mouseButton >= XCB_BUTTON_INDEX_4) { //scroll event, take pointer position configVals[0] = pointer->root_x; configVals[1] = pointer->root_y; } else { if (pointer->root_x > x + clientGeom->width) configVals[0] = pointer->root_x - clientGeom->width + 1; else configVals[0] = static_cast(x - clickPoint.x()); if (pointer->root_y > y + clientGeom->height) configVals[1] = pointer->root_y - clientGeom->height + 1; else configVals[1] = static_cast(y - clickPoint.y()); } xcb_configure_window(c, m_containerWid, XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y, configVals); //pull window up stackContainerWindow(XCB_STACK_MODE_ABOVE); //mouse down if (m_injectMode == Direct) { xcb_button_press_event_t* event = new xcb_button_press_event_t; memset(event, 0x00, sizeof(xcb_button_press_event_t)); event->response_type = XCB_BUTTON_PRESS; event->event = m_windowId; event->time = QX11Info::getTimestamp(); event->same_screen = 1; event->root = QX11Info::appRootWindow(); event->root_x = x; event->root_y = y; event->event_x = static_cast(clickPoint.x()); event->event_y = static_cast(clickPoint.y()); event->child = 0; event->state = 0; event->detail = mouseButton; xcb_send_event(c, false, m_windowId, XCB_EVENT_MASK_BUTTON_PRESS, (char *) event); delete event; } else { // sendXTestPressed(QX11Info::display(), mouseButton); } //mouse up if (m_injectMode == Direct) { xcb_button_release_event_t* event = new xcb_button_release_event_t; memset(event, 0x00, sizeof(xcb_button_release_event_t)); event->response_type = XCB_BUTTON_RELEASE; event->event = m_windowId; event->time = QX11Info::getTimestamp(); event->same_screen = 1; event->root = QX11Info::appRootWindow(); event->root_x = x; event->root_y = y; event->event_x = static_cast(clickPoint.x()); event->event_y = static_cast(clickPoint.y()); event->child = 0; event->state = 0; event->detail = mouseButton; xcb_send_event(c, false, m_windowId, XCB_EVENT_MASK_BUTTON_RELEASE, (char *) event); delete event; } else { // sendXTestReleased(QX11Info::display(), mouseButton); } #ifndef VISUAL_DEBUG stackContainerWindow(XCB_STACK_MODE_BELOW); #endif sendingClickEvent = false; } ukui-panel-3.0.6.4/sni-xembed-proxy/resources/0000755000175000017500000000000014203402514017573 5ustar fengfengukui-panel-3.0.6.4/sni-xembed-proxy/resources/sni-xembed-proxy.desktop0000644000175000017500000000041214203402514024375 0ustar fengfeng[Desktop Entry] Name=sni-xembed-proxy Name[zh_CN]=x转sni服务 Comment=sni-xembed-proxy Comment[zh_CN]=x转sni服务 Exec=sni-xembed-proxy Terminal=false Type=Application OnlyShowIn=UKUI NoDisplay=true X-UKUI-AutoRestart=true X-UKUI-Autostart-Phase=Initialization ukui-panel-3.0.6.4/sni-xembed-proxy/CMakeLists.txt0000644000175000017500000000313614203402514020324 0ustar fengfengcmake_minimum_required(VERSION 3.1.0) project(sni-xembed-proxy) #判断编译器类型,如果是gcc编译器,则在编译选项中加入c++11支持 if(CMAKE_COMPILER_IS_GNUCXX) set(CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}") message(STATUS "optional:-std=c++11") endif(CMAKE_COMPILER_IS_GNUCXX) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) set(CMAKE_AUTOUIC ON) if(CMAKE_VERSION VERSION_LESS "3.7.0") set(CMAKE_INCLUDE_CURRENT_DIR ON) endif() find_package(Qt5 COMPONENTS Widgets Network REQUIRED) find_package(Qt5DBus REQUIRED) find_package(PkgConfig REQUIRED) find_package(KF5WindowSystem REQUIRED) find_package(Qt5X11Extras REQUIRED) add_executable(sni-xembed-proxy main.cpp snixembedproxy.cpp sniproxy.cpp snidbus.cpp statusnotifierwatcher_interface.cpp ../panel-daemon/convert-desktop-windowid/convertdesktoptowinid.cpp snixembedproxy.h sniproxy.h snidbus.h statusnotifierwatcher_interface.h systemtraytypedefs.h xcbutilss.h ../panel-daemon/convert-desktop-windowid/convertdesktoptowinid.h ) target_link_libraries(sni-xembed-proxy Qt5::X11Extras Qt5::Widgets Qt5::DBus KF5::WindowSystem xcb xcb-util xcb-damage xcb-image xcb-composite xcb-shape -lukui-log4qt -lQt5Xdg ) add_definitions(-DQT_NO_KEYWORDS) add_definitions(-DQT_MESSAGELOGCONTEXT) install(TARGETS sni-xembed-proxy DESTINATION bin) install(FILES resources/sni-xembed-proxy.desktop DESTINATION "/etc/xdg/autostart/" COMPONENT Runtime ) ukui-panel-3.0.6.4/sni-xembed-proxy/systemtraytypedefs.h0000755000175000017500000000365114203402514021732 0ustar fengfeng/*************************************************************************** * * * Copyright (C) 2009 Marco Martin * * * * 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. * * * * 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 . * ***************************************************************************/ #ifndef SYSTEMTRAYTYPEDEFS_H #define SYSTEMTRAYTYPEDEFS_H #include #include #include struct KDbusImageStruct { int width; int height; QByteArray data; }; typedef QVector KDbusImageVector; struct KDbusToolTipStruct { QString icon; KDbusImageVector image; QString title; QString subTitle; }; Q_DECLARE_METATYPE(KDbusImageStruct) Q_DECLARE_METATYPE(KDbusImageVector) Q_DECLARE_METATYPE(KDbusToolTipStruct) #endif ukui-panel-3.0.6.4/sni-xembed-proxy/statusnotifierwatcher_interface.h0000644000175000017500000000535414203402514024422 0ustar fengfeng/* * This file was generated by qdbusxml2cpp version 0.8 * Command line was: qdbusxml2cpp -m -c OrgKdeStatusNotifierWatcherInterface -i systemtraytypedefs.h -p statusnotifierwatcher_interface kf5_org.kde.StatusNotifierWatcher.xml * * qdbusxml2cpp is Copyright (C) 2020 The Qt Company Ltd. * * This is an auto-generated file. * Do not edit! All changes made to it will be lost. */ #ifndef STATUSNOTIFIERWATCHER_INTERFACE_H #define STATUSNOTIFIERWATCHER_INTERFACE_H #include #include #include #include #include #include #include #include //#include "systemtraytypedefs.h" #include "snidbus.h" /* * Proxy class for interface org.kde.StatusNotifierWatcher */ class OrgKdeStatusNotifierWatcherInterface: public QDBusAbstractInterface { Q_OBJECT public: static inline const char *staticInterfaceName() { return "org.kde.StatusNotifierWatcher"; } public: OrgKdeStatusNotifierWatcherInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr); ~OrgKdeStatusNotifierWatcherInterface(); Q_PROPERTY(bool IsStatusNotifierHostRegistered READ isStatusNotifierHostRegistered) inline bool isStatusNotifierHostRegistered() const { return qvariant_cast< bool >(property("IsStatusNotifierHostRegistered")); } Q_PROPERTY(int ProtocolVersion READ protocolVersion) inline int protocolVersion() const { return qvariant_cast< int >(property("ProtocolVersion")); } Q_PROPERTY(QStringList RegisteredStatusNotifierItems READ registeredStatusNotifierItems) inline QStringList registeredStatusNotifierItems() const { return qvariant_cast< QStringList >(property("RegisteredStatusNotifierItems")); } public Q_SLOTS: // METHODS inline QDBusPendingReply<> RegisterStatusNotifierHost(const QString &service) { QList argumentList; argumentList << QVariant::fromValue(service); return asyncCallWithArgumentList(QStringLiteral("RegisterStatusNotifierHost"), argumentList); } inline QDBusPendingReply<> RegisterStatusNotifierItem(const QString &service) { QList argumentList; argumentList << QVariant::fromValue(service); return asyncCallWithArgumentList(QStringLiteral("RegisterStatusNotifierItem"), argumentList); } Q_SIGNALS: // SIGNALS void StatusNotifierHostRegistered(); void StatusNotifierHostUnregistered(); void StatusNotifierItemRegistered(const QString &in0); void StatusNotifierItemUnregistered(const QString &in0); }; namespace org { namespace kde { typedef ::OrgKdeStatusNotifierWatcherInterface StatusNotifierWatcher; } } #endif ukui-panel-3.0.6.4/sni-xembed-proxy/xcbutilss.h0000755000175000017500000000702214203402514017756 0ustar fengfeng/******************************************************************** Copyright (C) 2012, 2013 Martin Graesslin Copyright (C) 2015 David Edmudson 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. You should have received a copy of the GNU General Public License along with this program. If not, see . *********************************************************************/ #ifndef KWIN_XCB_UTILS_H #define KWIN_XCB_UTILS_H #include #include #include #include #include #include #include #include #include #include /** XEMBED messages */ #define XEMBED_EMBEDDED_NOTIFY 0 #define XEMBED_WINDOW_ACTIVATE 1 #define XEMBED_WINDOW_DEACTIVATE 2 #define XEMBED_REQUEST_FOCUS 3 #define XEMBED_FOCUS_IN 4 #define XEMBED_FOCUS_OUT 5 #define XEMBED_FOCUS_NEXT 6 #define XEMBED_FOCUS_PREV 7 namespace Xcb { typedef xcb_window_t WindowId; template using ScopedCPointer = QScopedPointer; class Atom { public: explicit Atom(const QByteArray &name, bool onlyIfExists = false, xcb_connection_t *c = QX11Info::connection()) : m_connection(c) , m_retrieved(false) , m_cookie(xcb_intern_atom_unchecked(m_connection, onlyIfExists, name.length(), name.constData())) , m_atom(XCB_ATOM_NONE) , m_name(name) { } Atom() = delete; Atom(const Atom &) = delete; ~Atom() { if (!m_retrieved && m_cookie.sequence) { xcb_discard_reply(m_connection, m_cookie.sequence); } } operator xcb_atom_t() const { (const_cast(this))->getReply(); return m_atom; } bool isValid() { getReply(); return m_atom != XCB_ATOM_NONE; } bool isValid() const { (const_cast(this))->getReply(); return m_atom != XCB_ATOM_NONE; } inline const QByteArray &name() const { return m_name; } private: void getReply() { if (m_retrieved || !m_cookie.sequence) { return; } ScopedCPointer reply(xcb_intern_atom_reply(m_connection, m_cookie, nullptr)); if (!reply.isNull()) { m_atom = reply->atom; } m_retrieved = true; } xcb_connection_t *m_connection; bool m_retrieved; xcb_intern_atom_cookie_t m_cookie; xcb_atom_t m_atom; QByteArray m_name; }; class Atoms { public: Atoms() : xembedAtom("_XEMBED"), selectionAtom(xcb_atom_name_by_screen("_NET_SYSTEM_TRAY", QX11Info::appScreen())), opcodeAtom("_NET_SYSTEM_TRAY_OPCODE"), messageData("_NET_SYSTEM_TRAY_MESSAGE_DATA"), visualAtom("_NET_SYSTEM_TRAY_VISUAL") {} Atom xembedAtom; Atom selectionAtom; Atom opcodeAtom; Atom messageData; Atom visualAtom; }; extern Atoms* atoms; } // namespace Xcb #endif // KWIN_XCB_UTILS_H ukui-panel-3.0.6.4/sni-xembed-proxy/kf5_org.kde.StatusNotifierItem.xml0000644000175000017500000000602714203402514024207 0ustar fengfeng ukui-panel-3.0.6.4/sni-xembed-proxy/sniproxy.h0000755000175000017500000001126014203402514017630 0ustar fengfeng/* * Holds one embedded window, registers as DBus entry * Copyright (C) 2015 David Edmundson * Copyright (C) 2019 Konrad Materka * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * */ #ifndef SNI_PROXY_H #define SNI_PROXY_H #include #include #include #include #include #include #include #include #include "snidbus.h" #include "../panel-daemon/convert-desktop-windowid/convertdesktoptowinid.h" class SNIProxy : public QObject { Q_OBJECT Q_CLASSINFO("D-Bus Interface", "org.kde.StatusNotifierItem") Q_PROPERTY(QString Category READ Category) Q_PROPERTY(QString Id READ Id) Q_PROPERTY(QString Title READ Title) Q_PROPERTY(QString Status READ Status) Q_PROPERTY(int WindowId READ WindowId) Q_PROPERTY(bool ItemIsMenu READ ItemIsMenu) Q_PROPERTY(KDbusImageVector IconPixmap READ IconPixmap) public: explicit SNIProxy(xcb_window_t wid, QObject *parent = nullptr); ~SNIProxy() override; void update(); void resizeWindow(const uint16_t width, const uint16_t height) const; void hideContainerWindow(xcb_window_t windowId) const; /** * @return the category of the application associated to this item * @see Category */ QString Category() const; /** * @return the id of this item */ QString Id() const; /** * @return the title of this item */ QString Title() const; /** * @return The status of this item * @see Status */ QString Status() const; /** * @return The id of the main window of the application that controls the item */ int WindowId() const; /** * @return The item only support the context menu, the visualization should prefer sending ContextMenu() instead of Activate() */ bool ItemIsMenu() const; /** * @return a serialization of the icon data */ KDbusImageVector IconPixmap() const; public Q_SLOTS: //interaction /** * Shows the context menu associated to this item * at the desired screen position */ void ContextMenu(int x, int y); /** * Shows the main widget and try to position it on top * of the other windows, if the widget is already visible, hide it. */ void Activate(int x, int y); /** * The user activated the item in an alternate way (for instance with middle mouse button, this depends from the systray implementation) */ void SecondaryActivate(int x, int y); /** * Inform this item that the mouse wheel was used on its representation */ void Scroll(int delta, const QString &orientation); Q_SIGNALS: /** * Inform the systemtray that the own main icon has been changed, * so should be reloaded */ void NewIcon(); /** * Inform the systemtray that there is a new icon to be used as overlay */ void NewOverlayIcon(); /** * Inform the systemtray that the requesting attention icon * has been changed, so should be reloaded */ void NewAttentionIcon(); /** * Inform the systemtray that something in the tooltip has been changed */ void NewToolTip(); /** * Signal the new status when it has been changed * @see Status */ void NewStatus(const QString &status); private: enum InjectMode { Direct, XTest }; QSize calculateClientWindowSize() const; void sendClick(uint8_t mouseButton, int x, int y); QImage getImageNonComposite() const; bool isTransparentImage(const QImage &image) const; QImage convertFromNative(xcb_image_t *xcbImage) const; QPoint calculateClickPoint() const; void stackContainerWindow(const uint32_t stackMode) const; QDBusConnection m_dbus; xcb_window_t m_windowId; xcb_window_t m_containerWid; static int s_serviceCount; QPixmap m_pixmap; bool sendingClickEvent; InjectMode m_injectMode; }; #endif // SNIPROXY_H ukui-panel-3.0.6.4/sni-xembed-proxy/main.cpp0000644000175000017500000000306114203402514017211 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include "xcbutilss.h" namespace Xcb { Xcb::Atoms* atoms; } int main(int argc, char *argv[]) { initUkuiLog4qt("sni-xembed-proxy"); qputenv("QT_QPA_PLATFORM", "xcb"); QGuiApplication::setDesktopSettingsAware(false); QApplication app(argc, argv); auto disableSessionManagement = [](QSessionManager &sm) { sm.setRestartHint(QSessionManager::RestartNever); }; QObject::connect(&app, &QGuiApplication::commitDataRequest, disableSessionManagement); QObject::connect(&app, &QGuiApplication::saveStateRequest, disableSessionManagement); app.setQuitOnLastWindowClosed(false); Xcb::atoms = new Xcb::Atoms(); SniXembedProxy proxy; auto rc = app.exec(); delete Xcb::atoms; return rc; } ukui-panel-3.0.6.4/sni-daemon/0000755000175000017500000000000014204636772014421 5ustar fengfengukui-panel-3.0.6.4/sni-daemon/snideamo.h0000644000175000017500000000373514204636772016401 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include class SniDeamo : public QObject,protected QDBusContext { Q_OBJECT Q_CLASSINFO("D-Bus Interface", "org.kde.StatusNotifierWatcher") Q_PROPERTY(QStringList RegisteredStatusNotifierItems READ RegisteredStatusNotifierItems) Q_PROPERTY(bool IsStatusNotifierHostRegistered READ IsStatusNotifierHostRegistered) Q_PROPERTY(int ProtocolVersion READ ProtocolVersion) public: SniDeamo(); ~SniDeamo(); QStringList RegisteredStatusNotifierItems() const; bool IsStatusNotifierHostRegistered() const; int ProtocolVersion() const; public Q_SLOTS: void RegisterStatusNotifierItem(const QString &service); void RegisterStatusNotifierHost(const QString &service); private: QDBusServiceWatcher *m_serviceWatcher = nullptr; QStringList m_registeredServices; QSet m_statusNotifierHostServices; Q_SIGNALS: void StatusNotifierItemRegistered(const QString &service); void StatusNotifierItemUnregistered(const QString &service); void StatusNotifierHostRegistered(); void StatusNotifierHostUnregistered(); protected Q_SLOTS: void serviceUnregistered(const QString& name); }; #endif // SNIDEAMO_H ukui-panel-3.0.6.4/sni-daemon/snidaemon.h0000644000175000017500000000374414203402514016537 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include class SniDaemon : public QObject, protected QDBusContext { Q_OBJECT Q_CLASSINFO("D-Bus Interface", "org.kde.StatusNotifierWatcher") Q_PROPERTY(QStringList RegisteredStatusNotifierItems READ RegisteredStatusNotifierItems) Q_PROPERTY(bool IsStatusNotifierHostRegistered READ IsStatusNotifierHostRegistered) Q_PROPERTY(int ProtocolVersion READ ProtocolVersion) public: SniDaemon(); ~SniDaemon(); QStringList RegisteredStatusNotifierItems() const; bool IsStatusNotifierHostRegistered() const; int ProtocolVersion() const; public Q_SLOTS: void RegisterStatusNotifierItem(const QString &service); void RegisterStatusNotifierHost(const QString &service); private: QDBusServiceWatcher *m_serviceWatcher = nullptr; QStringList m_registeredServices; QSet m_statusNotifierHostServices; Q_SIGNALS: void StatusNotifierItemRegistered(const QString &service); void StatusNotifierItemUnregistered(const QString &service); void StatusNotifierHostRegistered(); void StatusNotifierHostUnregistered(); protected Q_SLOTS: void serviceUnregistered(const QString& name); }; #endif // SNIDAEMON_H ukui-panel-3.0.6.4/sni-daemon/statusnotifieritem_interface.cpp0000644000175000017500000000223614203402514023072 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see setConnection(dbus); m_serviceWatcher->setWatchMode(QDBusServiceWatcher::WatchForUnregistration); connect(m_serviceWatcher, &QDBusServiceWatcher::serviceUnregistered, this, &SniDaemon::serviceUnregistered); } SniDaemon::~SniDaemon() { QDBusConnection dbus = QDBusConnection::sessionBus(); dbus.unregisterService(QStringLiteral("org.kde.StatusNotifierWatcher")); } void SniDaemon::serviceUnregistered(const QString& name) { qDebug()<<"Service "<< name << "unregistered"; m_serviceWatcher->removeWatchedService(name); QString match = name + QLatin1Char('/'); QStringList::Iterator it = m_registeredServices.begin(); qDebug()<startsWith(match)) { QString name = *it; it = m_registeredServices.erase(it); emit StatusNotifierItemUnregistered(name); } else { ++it; } } if (m_statusNotifierHostServices.contains(name)) { m_statusNotifierHostServices.remove(name); emit StatusNotifierHostUnregistered(); } } void SniDaemon::RegisterStatusNotifierItem(const QString &serviceOrPath) { QString service; QString path; if (serviceOrPath.startsWith(QLatin1Char('/'))) { service = message().service(); path = serviceOrPath; } else { service = serviceOrPath; path = QStringLiteral("/StatusNotifierItem"); } QString notifierItemId = service + path; if (m_registeredServices.contains(notifierItemId)) { return; } m_serviceWatcher->addWatchedService(service); if (QDBusConnection::sessionBus().interface()->isServiceRegistered(service).value()) { //check if the service has registered a SystemTray object org::kde::StatusNotifierItem trayclient(service, path, QDBusConnection::sessionBus()); if (trayclient.isValid()) { qDebug() << "Registering" << notifierItemId << "to system tray"; m_registeredServices.append(notifierItemId); emit StatusNotifierItemRegistered(notifierItemId); } else { m_serviceWatcher->removeWatchedService(service); } } else { m_serviceWatcher->removeWatchedService(service); } } void SniDaemon::RegisterStatusNotifierHost(const QString &service) { if (service.contains(QLatin1String("org.kde.StatusNotifierHost-")) && QDBusConnection::sessionBus().interface()->isServiceRegistered(service).value() && !m_statusNotifierHostServices.contains(service)) { qDebug()<<"Registering"<addWatchedService(service); emit StatusNotifierHostRegistered(); } } QStringList SniDaemon::RegisteredStatusNotifierItems() const { return m_registeredServices; } bool SniDaemon::IsStatusNotifierHostRegistered() const { return !m_statusNotifierHostServices.isEmpty(); } int SniDaemon::ProtocolVersion() const { return 0; } ukui-panel-3.0.6.4/sni-daemon/resources/0000755000175000017500000000000014203402514016413 5ustar fengfengukui-panel-3.0.6.4/sni-daemon/resources/sni-daemon.desktop0000644000175000017500000000037414203402514022044 0ustar fengfeng[Desktop Entry] Name=sni-daemon Name[zh_CN]=sni后台服务 Comment=sni-daemon Comment[zh_CN]=sni后台服务 Exec=sni-daemon Terminal=false Type=Application OnlyShowIn=UKUI NoDisplay=true X-UKUI-AutoRestart=true X-UKUI-Autostart-Phase=Initialization ukui-panel-3.0.6.4/sni-daemon/CMakeLists.txt0000644000175000017500000000210514203402514017137 0ustar fengfengcmake_minimum_required(VERSION 3.1.0) project(sni-daemon) #判断编译器类型,如果是gcc编译器,则在编译选项中加入c++11支持 if(CMAKE_COMPILER_IS_GNUCXX) set(CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}") message(STATUS "optional:-std=c++11") endif(CMAKE_COMPILER_IS_GNUCXX) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) set(CMAKE_AUTOUIC ON) if(CMAKE_VERSION VERSION_LESS "3.7.0") set(CMAKE_INCLUDE_CURRENT_DIR ON) endif() find_package(Qt5 COMPONENTS Widgets Network REQUIRED) find_package(Qt5DBus REQUIRED) find_package(PkgConfig REQUIRED) add_executable(sni-daemon main.cpp snidaemon.cpp statusnotifieritem_interface.cpp snidaemon.h statusnotifieritem_interface.h systemtraytypedefs.h ) target_link_libraries(sni-daemon Qt5::Widgets Qt5::DBus -lukui-log4qt ) add_definitions(-DQT_MESSAGELOGCONTEXT) install(TARGETS sni-daemon DESTINATION bin) install(FILES resources/sni-daemon.desktop DESTINATION "/etc/xdg/autostart/" COMPONENT Runtime ) ukui-panel-3.0.6.4/sni-daemon/statusnotifieritem_interface.h0000644000175000017500000001270014203402514022534 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include #include #include #include #include "systemtraytypedefs.h" /* * Proxy class for interface org.kde.StatusNotifierItem */ class OrgKdeStatusNotifierItemInterface: public QDBusAbstractInterface { Q_OBJECT public: static inline const char *staticInterfaceName() { return "org.kde.StatusNotifierItem"; } public: OrgKdeStatusNotifierItemInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr); ~OrgKdeStatusNotifierItemInterface(); Q_PROPERTY(QString AttentionIconName READ attentionIconName) inline QString attentionIconName() const { return qvariant_cast< QString >(property("AttentionIconName")); } Q_PROPERTY(KDbusImageVector AttentionIconPixmap READ attentionIconPixmap) inline KDbusImageVector attentionIconPixmap() const { return qvariant_cast< KDbusImageVector >(property("AttentionIconPixmap")); } Q_PROPERTY(QString AttentionMovieName READ attentionMovieName) inline QString attentionMovieName() const { return qvariant_cast< QString >(property("AttentionMovieName")); } Q_PROPERTY(QString Category READ category) inline QString category() const { return qvariant_cast< QString >(property("Category")); } Q_PROPERTY(QString IconName READ iconName) inline QString iconName() const { return qvariant_cast< QString >(property("IconName")); } Q_PROPERTY(KDbusImageVector IconPixmap READ iconPixmap) inline KDbusImageVector iconPixmap() const { return qvariant_cast< KDbusImageVector >(property("IconPixmap")); } Q_PROPERTY(QString IconThemePath READ iconThemePath) inline QString iconThemePath() const { return qvariant_cast< QString >(property("IconThemePath")); } Q_PROPERTY(QString Id READ id) inline QString id() const { return qvariant_cast< QString >(property("Id")); } Q_PROPERTY(bool ItemIsMenu READ itemIsMenu) inline bool itemIsMenu() const { return qvariant_cast< bool >(property("ItemIsMenu")); } Q_PROPERTY(QDBusObjectPath Menu READ menu) inline QDBusObjectPath menu() const { return qvariant_cast< QDBusObjectPath >(property("Menu")); } Q_PROPERTY(QString OverlayIconName READ overlayIconName) inline QString overlayIconName() const { return qvariant_cast< QString >(property("OverlayIconName")); } Q_PROPERTY(KDbusImageVector OverlayIconPixmap READ overlayIconPixmap) inline KDbusImageVector overlayIconPixmap() const { return qvariant_cast< KDbusImageVector >(property("OverlayIconPixmap")); } Q_PROPERTY(QString Status READ status) inline QString status() const { return qvariant_cast< QString >(property("Status")); } Q_PROPERTY(QString Title READ title) inline QString title() const { return qvariant_cast< QString >(property("Title")); } Q_PROPERTY(KDbusToolTipStruct ToolTip READ toolTip) inline KDbusToolTipStruct toolTip() const { return qvariant_cast< KDbusToolTipStruct >(property("ToolTip")); } Q_PROPERTY(int WindowId READ windowId) inline int windowId() const { return qvariant_cast< int >(property("WindowId")); } public Q_SLOTS: // METHODS inline QDBusPendingReply<> Activate(int x, int y) { QList argumentList; argumentList << QVariant::fromValue(x) << QVariant::fromValue(y); return asyncCallWithArgumentList(QStringLiteral("Activate"), argumentList); } inline QDBusPendingReply<> ContextMenu(int x, int y) { QList argumentList; argumentList << QVariant::fromValue(x) << QVariant::fromValue(y); return asyncCallWithArgumentList(QStringLiteral("ContextMenu"), argumentList); } inline QDBusPendingReply<> Scroll(int delta, const QString &orientation) { QList argumentList; argumentList << QVariant::fromValue(delta) << QVariant::fromValue(orientation); return asyncCallWithArgumentList(QStringLiteral("Scroll"), argumentList); } inline QDBusPendingReply<> SecondaryActivate(int x, int y) { QList argumentList; argumentList << QVariant::fromValue(x) << QVariant::fromValue(y); return asyncCallWithArgumentList(QStringLiteral("SecondaryActivate"), argumentList); } Q_SIGNALS: // SIGNALS void NewAttentionIcon(); void NewIcon(); void NewOverlayIcon(); void NewStatus(const QString &status); void NewTitle(); void NewToolTip(); }; namespace org { namespace kde { typedef ::OrgKdeStatusNotifierItemInterface StatusNotifierItem; } } #endif ukui-panel-3.0.6.4/sni-daemon/systemtraytypedefs.h0000755000175000017500000000230614203402514020546 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include struct KDbusImageStruct { int width; int height; QByteArray data; }; typedef QVector KDbusImageVector; struct KDbusToolTipStruct { QString icon; KDbusImageVector image; QString title; QString subTitle; }; Q_DECLARE_METATYPE(KDbusImageStruct) Q_DECLARE_METATYPE(KDbusImageVector) Q_DECLARE_METATYPE(KDbusToolTipStruct) #endif ukui-panel-3.0.6.4/sni-daemon/main.cpp0000644000175000017500000000165414203402514016037 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include int main(int argc, char *argv[]) { initUkuiLog4qt("sni-daemon"); QApplication a(argc, argv); SniDaemon w; return a.exec(); } ukui-panel-3.0.6.4/sni-daemon/snideamo.cpp0000644000175000017500000001020414204636772016721 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see setConnection(dbus); m_serviceWatcher->setWatchMode(QDBusServiceWatcher::WatchForUnregistration); connect(m_serviceWatcher, &QDBusServiceWatcher::serviceUnregistered, this, &SniDeamo::serviceUnregistered); } SniDeamo::~SniDeamo() { QDBusConnection dbus = QDBusConnection::sessionBus(); dbus.unregisterService(QStringLiteral("org.kde.StatusNotifierWatcher")); } void SniDeamo::serviceUnregistered(const QString& name) { qDebug()<<"Service "<< name << "unregistered"; m_serviceWatcher->removeWatchedService(name); QString match = name + QLatin1Char('/'); QStringList::Iterator it = m_registeredServices.begin(); qDebug()<startsWith(match)) { QString name = *it; it = m_registeredServices.erase(it); emit StatusNotifierItemUnregistered(name); } else { ++it; } } if (m_statusNotifierHostServices.contains(name)) { m_statusNotifierHostServices.remove(name); emit StatusNotifierHostUnregistered(); } } void SniDeamo::RegisterStatusNotifierItem(const QString &serviceOrPath) { QString service; QString path; if (serviceOrPath.startsWith(QLatin1Char('/'))) { service = message().service(); path = serviceOrPath; } else { service = serviceOrPath; path = QStringLiteral("/StatusNotifierItem"); } QString notifierItemId = service + path; if (m_registeredServices.contains(notifierItemId)) { return; } m_serviceWatcher->addWatchedService(service); if (QDBusConnection::sessionBus().interface()->isServiceRegistered(service).value()) { //check if the service has registered a SystemTray object org::kde::StatusNotifierItem trayclient(service, path, QDBusConnection::sessionBus()); if (trayclient.isValid()) { qDebug() << "Registering" << notifierItemId << "to system tray"; m_registeredServices.append(notifierItemId); emit StatusNotifierItemRegistered(notifierItemId); } else { m_serviceWatcher->removeWatchedService(service); } } else { m_serviceWatcher->removeWatchedService(service); } } void SniDeamo::RegisterStatusNotifierHost(const QString &service) { if (service.contains(QLatin1String("org.kde.StatusNotifierHost-")) && QDBusConnection::sessionBus().interface()->isServiceRegistered(service).value() && !m_statusNotifierHostServices.contains(service)) { qDebug()<<"Registering"<addWatchedService(service); emit StatusNotifierHostRegistered(); } } QStringList SniDeamo::RegisteredStatusNotifierItems() const { return m_registeredServices; } bool SniDeamo::IsStatusNotifierHostRegistered() const { return !m_statusNotifierHostServices.isEmpty(); } int SniDeamo::ProtocolVersion() const { return 0; } ukui-panel-3.0.6.4/plugin-taskbar-wayland/0000755000175000017500000000000014204636772016747 5ustar fengfengukui-panel-3.0.6.4/plugin-taskbar-wayland/ukuitaskbutton.h0000644000175000017500000001210214204636772022210 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2011 Razor team * 2014 LXQt team * Authors: * Alexander Sokoloff * Kuzma Shapran * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef UKUITASKBUTTON_H #define UKUITASKBUTTON_H #include #include #include #include #include "../panel/iukuipanel.h" //#include #include class QPainter; class QPalette; class QMimeData; class UKUITaskGroup; class UKUITaskBar; class LeftAlignedTextStyle : public QProxyStyle { using QProxyStyle::QProxyStyle; public: virtual void drawItemText(QPainter * painter, const QRect & rect, int flags , const QPalette & pal, bool enabled, const QString & text , QPalette::ColorRole textRole = QPalette::NoRole) const override; }; class UKUITaskButton : public QToolButton { Q_OBJECT Q_PROPERTY(Qt::Corner origin READ origin WRITE setOrigin) public: explicit UKUITaskButton(QString appName, const WId window, UKUITaskBar * taskBar, QWidget *parent = 0); explicit UKUITaskButton(QString iconName, QString caption, const WId window, UKUITaskBar * taskbar, QWidget *parent = 0); virtual ~UKUITaskButton(); bool isApplicationHidden() const; bool isApplicationActive() const; WId windowId() const { return mWindow; } bool hasUrgencyHint() const { return mUrgencyHint; } void setUrgencyHint(bool set); bool isOnDesktop(int desktop) const; bool isOnCurrentScreen() const; bool isMinimized() const; void updateText(); void setLeaderWindow(WId leaderWindow); bool isLeaderWindow(WId compare) { return mWindow == compare; } Qt::Corner origin() const; virtual void setAutoRotation(bool value, IUKUIPanel::Position position); UKUITaskBar * parentTaskBar() const {return mParentTaskBar;} void refreshIconGeometry(QRect const & geom); static QString mimeDataFormat() { return QLatin1String("ukui/UKUITaskButton"); } /*! \return true if this buttom received DragEnter event (and no DragLeave event yet) * */ bool hasDragAndDropHover() const; void setGroupIcon(QIcon ico); bool isWinActivate; //1为激活状态,0为隐藏状态 QString mIconName; QString mCaption; public slots: void raiseApplication(); void minimizeApplication(); void maximizeApplication(); void deMaximizeApplication(); void shadeApplication(); void unShadeApplication(); void closeApplication(); void moveApplicationToDesktop(); void moveApplication(); void resizeApplication(); void setApplicationLayer(); void setOrigin(Qt::Corner); void updateIcon(); protected: virtual void dragEnterEvent(QDragEnterEvent *event); virtual void dragMoveEvent(QDragMoveEvent * event); virtual void dragLeaveEvent(QDragLeaveEvent *event); virtual void dropEvent(QDropEvent *event); void mousePressEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); virtual void contextMenuEvent(QContextMenuEvent *event); void enterEvent(QEvent *); void leaveEvent(QEvent *); void paintEvent(QPaintEvent *); void setWindowId(WId wid) {mWindow = wid;} virtual QMimeData * mimeData(); static bool sDraggging; inline IUKUIPanelPlugin * plugin() const { return mPlugin; } private: WId mWindow; QString mAppName; bool mUrgencyHint; QPoint mDragStartPosition; Qt::Corner mOrigin; QPixmap mPixmap; bool mDrawPixmap; UKUITaskBar * mParentTaskBar; IUKUIPanelPlugin * mPlugin; enum TaskButtonStatus{NORMAL, HOVER, PRESS}; TaskButtonStatus taskbuttonstatus; QIcon mIcon; // Timer for when draggind something into a button (the button's window // must be activated so that the use can continue dragging to the window QTimer * mDNDTimer; QGSettings *gsettings; private slots: void activateWithDraggable(); signals: void dropped(QObject * dragSource, QPoint const & pos); void dragging(QObject * dragSource, QPoint const & pos); }; //typedef QHash UKUITaskButtonHash; //typedef QHash UKUITaskButtonHash; #endif // UKUITASKBUTTON_H ukui-panel-3.0.6.4/plugin-taskbar-wayland/ukuitaskbarplugin.h0000644000175000017500000000407514204636772022672 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2012 Razor team * 2014 LXQt team * Authors: * Alexander Sokoloff * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef UKUITASKBARPLUGIN_H #define UKUITASKBARPLUGIN_H #include "../panel/iukuipanel.h" #include "../panel/iukuipanelplugin.h" #include "ukuitaskbar.h" #include class UKUITaskBar; class UKUITaskBarPlugin : public QObject, public IUKUIPanelPlugin { Q_OBJECT public: UKUITaskBarPlugin(const IUKUIPanelPluginStartupInfo &startupInfo); ~UKUITaskBarPlugin(); QString themeId() const { return "TaskBar"; } virtual Flags flags() const { return HaveConfigDialog | NeedsHandle; } QWidget *widget() { return mTaskBar; } void realign(); bool isSeparate() const { return true; } bool isExpandable() const { return true; } private: UKUITaskBar *mTaskBar; }; class UKUITaskBarPluginLibrary: public QObject, public IUKUIPanelPluginLibrary { Q_OBJECT // Q_PLUGIN_METADATA(IID "ukui.org/Panel/PluginInterface/3.0") Q_INTERFACES(IUKUIPanelPluginLibrary) public: IUKUIPanelPlugin *instance(const IUKUIPanelPluginStartupInfo &startupInfo) const { return new UKUITaskBarPlugin(startupInfo);} }; #endif // UKUITASKBARPLUGIN_H ukui-panel-3.0.6.4/plugin-taskbar-wayland/ukuitaskbaricon.h0000644000175000017500000000664114204636772022325 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include #include #include #include #include class UKUITaskBarIcon { private: QStringList filePathList; QSettings* setting=nullptr; protected: void recursiveSearchFile(const QString& _filePath);//遍历/usr/share/applications/文件夹 QStringList getSpecifiedCategoryAppList(QString categorystr);//获取指定类型应用列表 public: UKUITaskBarIcon(); ~UKUITaskBarIcon(); QVector createAppInfoVector();//创建应用信息容器 static QVector appInfoVector; static QVector desktopfpVector; static QVector alphabeticVector; static QVector functionalVector; static QVector commonUseVector; static QVector desktopAllVector; QMap mMapFindDesktopByAppName; QMap mMapFindIconByAppName; QMap mMapFindExeByAppName; void saveMapFromDeskptop(); QString getDeskTopName(QString _name); QString getIconName(QString _name); QString getExeName(QString _name); /** * 获取系统应用名称 * @param desktopfp 为应用.desktop文件所在路径 * @return 返回应用名称 */ QString getAppName(QString desktopfp);//获取应用名 QString getAppEnglishName(QString desktopfp);//获取英语英文名 QString getAppIcon(QString desktopfp);//获取应用图像 QString getAppCategories(QString desktopfp);//获取应用分类 QString getAppExec(QString desktopfp);//获取应用命令 QString getAppType(QString desktopfp);//获取应用类型 QString getAppComment(QString desktopfp);//获取应用注释 QStringList getDesktopFilePath();//获取系统deskyop文件路径 QString getDesktopPathByAppName(QString appname);//根据应用名获取deskyop文件路径 QString getDesktopPathByAppEnglishName(QString appname);//根据应用英文名获取deskyop文件路径 QVector getAlphabeticClassification();//获取字母分类 QVector getFunctionalClassification();//获取功能分类 QVector getCommonUseApp();//获取常用App QVector getDesktopAll(); // QStringList getRecentApp();//获取最近添加App bool matchingAppCategories(QString desktopfp,QStringList categorylist);//匹配应用Categories QString getAppNamePinyin(QString appname);//获取应用名拼音 //获取用户图像 QString getUserIcon(); //获取用户姓名 QString getUserName(); }; #endif // UKUITASKBARICON_H ukui-panel-3.0.6.4/plugin-taskbar-wayland/ukuitaskwidget.h0000644000175000017500000001205714204636772022171 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include "../panel/iukuipanel.h" //#include #include #include #include #include #include class QPainter; class QPalette; class QMimeData; class UKUITaskGroup; class UKUITaskBar; class UKUITaskCloseButton; class UKUITaskWidget : public QWidget { Q_OBJECT Q_PROPERTY(Qt::Corner origin READ origin WRITE setOrigin) public: explicit UKUITaskWidget(const WId window, UKUITaskBar * taskBar, QWidget *parent = 0); explicit UKUITaskWidget(QString iconName, const WId window, UKUITaskBar * taskbar, QWidget *parent = 0); virtual ~UKUITaskWidget(); bool isApplicationHidden() const; bool isApplicationActive() const; WId windowId() const { return mWindow; } bool hasUrgencyHint() const { return mUrgencyHint; } void setUrgencyHint(bool set); bool isOnDesktop(int desktop) const; bool isOnCurrentScreen() const; bool isMinimized() const; bool isFocusState() const; void setThumbFixedSize(int w); void setThumbScale(bool val); void setThumbMaximumSize(int w); void updateText(); Qt::Corner origin() const; virtual void setAutoRotation(bool value, IUKUIPanel::Position position); UKUITaskBar * parentTaskBar() const {return mParentTaskBar;} void refreshIconGeometry(QRect const & geom); static QString mimeDataFormat() { return QLatin1String("ukui/UKUITaskWidget"); } /*! \return true if this buttom received DragEnter event (and no DragLeave event yet) * */ bool hasDragAndDropHover() const; void setThumbNail(QPixmap _pixmap); void setTitleFixedWidth(int size); void updateTitle(); void removeThumbNail(); void addThumbNail(); void setPixmap(QPixmap mPixmap); int getWidth(); QPixmap getPixmap(); void wl_updateTitle(QString caption); void wl_updateIcon(QString iconName); public slots: void raiseApplication(); void minimizeApplication(); void maximizeApplication(); void deMaximizeApplication(); void shadeApplication(); void unShadeApplication(); void closeApplication(); void moveApplicationToDesktop(); void moveApplication(); void resizeApplication(); void setApplicationLayer(); /** * @brief setWindowKeepAbove * 窗口置顶 */ void setWindowKeepAbove(); /** * @brief setWindowStatusClear * 取消置顶 */ void setWindowStatusClear(); void setOrigin(Qt::Corner); void updateIcon(); protected: virtual void dragEnterEvent(QDragEnterEvent *event); virtual void dragMoveEvent(QDragMoveEvent * event); virtual void dragLeaveEvent(QDragLeaveEvent *event); virtual void dropEvent(QDropEvent *event); void mousePressEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); void enterEvent(QEvent *); void leaveEvent(QEvent *); void paintEvent(QPaintEvent *); void contextMenuEvent(QContextMenuEvent *event); void setWindowId(WId wid) {mWindow = wid;} virtual QMimeData * mimeData(); static bool sDraggging; inline IUKUIPanelPlugin * plugin() const { return mPlugin; } private: NET::States stat; WId mWindow; bool mUrgencyHint; QPoint mDragStartPosition; Qt::Corner mOrigin; QPixmap mPixmap; bool mDrawPixmap; UKUITaskBar * mParentTaskBar; IUKUIPanelPlugin * mPlugin; QLabel *mTitleLabel; QLabel *mThumbnailLabel; QLabel *mAppIcon; UKUITaskCloseButton *mCloseBtn; QVBoxLayout *mVWindowsLayout; QHBoxLayout *mTopBarLayout; bool isWaylandWidget = false; // Timer for when draggind something into a button (the button's window // must be activated so that the use can continue dragging to the window QTimer * mDNDTimer; enum TaskWidgetStatus{NORMAL, HOVER, PRESS}; TaskWidgetStatus status; bool taskWidgetPress; //按钮左键是否按下 private slots: void activateWithDraggable(); void closeGroup(); signals: void dropped(QObject * dragSource, QPoint const & pos); void dragging(QObject * dragSource, QPoint const & pos); void windowMaximize(); void closeSigtoPop(); void closeSigtoGroup(); }; typedef QHash UKUITaskButtonHash; #endif // UKUITASKWIDGET_H ukui-panel-3.0.6.4/plugin-taskbar-wayland/ukuitaskbarplugin.cpp0000644000175000017500000000253514204636772023224 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2012 Razor team * 2014 LXQt team * Authors: * Alexander Sokoloff * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "ukuitaskbarplugin.h" UKUITaskBarPlugin::UKUITaskBarPlugin(const IUKUIPanelPluginStartupInfo &startupInfo): QObject(), IUKUIPanelPlugin(startupInfo) { mTaskBar = new UKUITaskBar(this); } UKUITaskBarPlugin::~UKUITaskBarPlugin() { delete mTaskBar; } void UKUITaskBarPlugin::realign() { mTaskBar->realign(); } ukui-panel-3.0.6.4/plugin-taskbar-wayland/ukuitaskgroup.h0000644000175000017500000001504414204636772022041 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2011 Razor team * 2014 LXQt team * Authors: * Alexander Sokoloff * Maciej Płaza * Kuzma Shapran * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef UKUITASKGROUP_H #define UKUITASKGROUP_H #include "../panel/iukuipanel.h" #include "../panel/iukuipanelplugin.h" #include "ukuitaskbar.h" #include "ukuigrouppopup.h" #include "ukuitaskwidget.h" #include "ukuitaskbutton.h" #include #include #include #include "../panel/ukuipanelpluginconfigdialog.h" #include "../panel/pluginsettings.h" #include "../plugin-quicklaunch/quicklaunchaction.h" #include //#include #define DEKSTOP_FILE_PATH "/usr/share/applications/" #define GET_DESKTOP_EXEC_NAME_MAIN "cat %s | awk '{if($1~\"Exec=\")if($2~\"\%\"){print $1} else print}' | cut -d '=' -f 2" #define GET_DESKTOP_EXEC_NAME_BACK "cat %s | awk '{if($1~\"StartupWMClass=\")print $1}' | cut -d '=' -f 2" #define GET_DESKTOP_ICON "cat %s | awk '{if($1~\"Icon=\")print $1}' | cut -d '=' -f 2" #define GET_PROCESS_EXEC_NAME_MAIN "ps -aux | sed 's/ \\+/ /g' |awk '{if($2~\"%d\")print}'| cut -d ' ' -f 11-" #define USR_SHARE_APP_CURRENT "/usr/share/applications/." #define USR_SHARE_APP_UPER "/usr/share/applications/.." #define PEONY_TRASH "/usr/share/applications/peony-trash.desktop" #define PEONY_COMUTER "/usr/share/applications/peony-computer.desktop" #define PEONY_HOME "/usr/share/applications/peony-home.desktop" #define PEONY_MAIN "/usr/share/applications/peony.desktop" #define WAYLAND_GROUP_HIDE 0 #define WAYLAND_GROUP_ACTIVATE 1 #define WAYLAND_GROUP_CLOSE 2 class QVBoxLayout; class IUKUIPanelPlugin; class UKUIGroupPopup; class UKUiMasterPopup; class UKUITaskGroup: public UKUITaskButton { Q_OBJECT public: UKUITaskGroup(const QString & groupName, WId window, UKUITaskBar * parent); UKUITaskGroup(const QString & iconName, const QString & caption, WId window, UKUITaskBar *parent = 0); virtual ~UKUITaskGroup(); QString groupName() const { return mGroupName; } int buttonsCount() const; int visibleButtonsCount() const; void initVisibleHash(); QWidget * addWindow(WId id); QWidget * checkedButton() const; QWidget * wl_addWindow(WId id); // Returns the next or the previous button in the popup // if circular is true, then it will go around the list of buttons QWidget * getNextPrevChildButton(bool next, bool circular); bool onWindowChanged(WId window, NET::Properties prop, NET::Properties2 prop2); void setAutoRotation(bool value, IUKUIPanel::Position position); Qt::ToolButtonStyle popupButtonStyle() const; void setToolButtonsStyle(Qt::ToolButtonStyle style); void setPopupVisible(bool visible = true, bool fast = false); void removeWidget(); void removeSrollWidget(); bool isSetMaxWindow(); void showPreview(); int calcAverageWidth(); int calcAverageHeight(); void showAllWindowByList();//when number of window is more than 30,need show all window of app by a list void showAllWindowByThumbnail();//when number of window is no more than 30,need show all window of app by a thumbnail void singleWindowClick(); void VisibleWndRemoved(WId window); void setActivateState_wl(bool _state); void wl_widgetUpdateTitle(QString caption); bool CheckifWaylandGroup() {return isWaylandGroup;} public slots: void onWindowRemoved(WId window); void timeout(); protected: QMimeData * mimeData(); void leaveEvent(QEvent * event); void enterEvent(QEvent * event); void dragEnterEvent(QDragEnterEvent * event); void dragLeaveEvent(QDragLeaveEvent * event); void contextMenuEvent(QContextMenuEvent * event); void mouseMoveEvent(QMouseEvent * event); // void paintEvent(QPaintEvent *); int recalculateFrameHeight() const; int recalculateFrameWidth() const; void setLayOutForPostion(); void draggingTimerTimeout(); private slots: void onClicked(bool checked); void onChildButtonClicked(); void onActiveWindowChanged(WId window); void onDesktopChanged(int number); void closeGroup(); void refreshIconsGeometry(); void refreshVisibility(); void groupPopupShown(UKUITaskGroup* sender); void handleSavedEvent(); signals: void groupBecomeEmpty(QString name); void visibilityChanged(bool visible); void popupShown(UKUITaskGroup* sender); private: bool isWaylandGroup; void changeTaskButtonStyle(); QString mGroupName; UKUIGroupPopup * mPopup; QVBoxLayout *VLayout; UKUITaskButtonHash mButtonHash; UKUITaskButtonHash mVisibleHash; bool mPreventPopup; bool mSingleButton; //!< flag if this group should act as a "standard" button (no groupping or only one "shown" window in group) enum TaskGroupStatus{NORMAL, HOVER, PRESS}; enum TaskGroupEvent{ENTEREVENT, LEAVEEVENT, OTHEREVENT}; TaskGroupStatus taskgroupStatus; TaskGroupEvent mTaskGroupEvent; QWidget *mpWidget; QScrollArea *mpScrollArea; QEvent * mEvent; QTimer *mTimer; QSize recalculateFrameSize(); QPoint recalculateFramePosition(); void recalculateFrameIfVisible(); void adjustPopWindowSize(int width, int height); void v_adjustPopWindowSize(int width, int height, int v_all); void regroup(); QString file_name; QuickLaunchAction *mAct; void initActionsInRightButtonMenu(); void initDesktopFileName(WId window); void badBackFunctionToFindDesktop(); void winClickActivate_wl(bool _getActive); void closeGroup_wl(); }; #endif // UKUITASKGROUP_H ukui-panel-3.0.6.4/plugin-taskbar-wayland/ukuigrouppopup.cpp0000644000175000017500000001351114204636772022572 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2011 Razor team * 2014 LXQt team * Authors: * Alexander Sokoloff * Maciej Płaza * Kuzma Shapran * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "ukuigrouppopup.h" #include #include #include #include #include #include #include #include #include /************************************************ this class is just a container of window buttons the main purpose is showing window buttons in vertical layout and drag&drop feature inside group ************************************************/ UKUIGroupPopup::UKUIGroupPopup(UKUITaskGroup *group): QFrame(group), mGroup(group) { rightclick = false; Q_ASSERT(group); setAcceptDrops(true); setWindowFlags(Qt::FramelessWindowHint | Qt::ToolTip); setAttribute(Qt::WA_AlwaysShowToolTips); setAttribute(Qt::WA_TranslucentBackground); setLayout(new QHBoxLayout); layout()->setSpacing(3); layout()->setMargin(3); connect(&mCloseTimer, &QTimer::timeout, this, &UKUIGroupPopup::closeTimerSlot); mCloseTimer.setSingleShot(true); mCloseTimer.setInterval(400); setMaximumWidth(QApplication::screens().at(0)->size().width()); setMaximumHeight(QApplication::screens().at(0)->size().height()); } UKUIGroupPopup::~UKUIGroupPopup() { } void UKUIGroupPopup::dropEvent(QDropEvent *event) { qlonglong temp; QDataStream stream(event->mimeData()->data(UKUITaskButton::mimeDataFormat())); stream >> temp; WId window = (WId) temp; UKUITaskButton *button = nullptr; int oldIndex(0); // get current position of the button being dragged for (int i = 0; i < layout()->count(); i++) { UKUITaskButton *b = qobject_cast(layout()->itemAt(i)->widget()); if (b && b->windowId() == window) { button = b; oldIndex = i; break; } } if (button == nullptr) return; int newIndex = -1; // find the new position to place it in for (int i = 0; i < oldIndex && newIndex == -1; i++) { QWidget *w = layout()->itemAt(i)->widget(); if (w && w->pos().y() + w->height() / 2 > event->pos().y()) newIndex = i; } const int size = layout()->count(); for (int i = size - 1; i > oldIndex && newIndex == -1; i--) { QWidget *w = layout()->itemAt(i)->widget(); if (w && w->pos().y() + w->height() / 2 < event->pos().y()) newIndex = i; } if (newIndex == -1 || newIndex == oldIndex) return; QVBoxLayout * l = qobject_cast(layout()); l->takeAt(oldIndex); l->insertWidget(newIndex, button); l->invalidate(); } void UKUIGroupPopup::dragEnterEvent(QDragEnterEvent *event) { event->accept(); QWidget::dragEnterEvent(event); } void UKUIGroupPopup::dragLeaveEvent(QDragLeaveEvent *event) { hide(false/*not fast*/); QFrame::dragLeaveEvent(event); } /************************************************ * ************************************************/ void UKUIGroupPopup::leaveEvent(QEvent *event) { // qDebug()<<"UKUIGroupPopup::leaveEvent:"<button() == Qt::RightButton && !mGroup->CheckifWaylandGroup()) rightclick = true; else rightclick = false; } void UKUIGroupPopup::paintEvent(QPaintEvent *event) { QPainter p(this); QStyleOption opt; opt.initFrom(this); p.setBrush(QBrush(QColor(0xff,0x14,0x14,0xb2))); style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); } void UKUIGroupPopup::hide(bool fast) { if (fast) close(); else mCloseTimer.start(); } void UKUIGroupPopup::show() { mCloseTimer.stop(); QFrame::show(); } void UKUIGroupPopup::closeTimerSlot() { bool button_has_dnd_hover = false; QLayout* l = layout(); for (int i = 0; l->count() > i; ++i) { UKUITaskWidget const * const button = dynamic_cast(l->itemAt(i)->widget()); if (0 != button && button->hasDragAndDropHover()) { button_has_dnd_hover = true; break; } } if (!button_has_dnd_hover) close(); } ukui-panel-3.0.6.4/plugin-taskbar-wayland/ukuitaskclosebutton.h0000644000175000017500000000221314204636772023240 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include class UKUITaskCloseButton : public QToolButton { Q_OBJECT public: explicit UKUITaskCloseButton(const WId window, QWidget *parent = 0); void mousePressEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event); private: WId mWindow; signals: void sigClicked(); }; #endif // UKUITASKCLOSEBUTTON_H ukui-panel-3.0.6.4/plugin-taskbar-wayland/resources/0000755000175000017500000000000014204636772020761 5ustar fengfengukui-panel-3.0.6.4/plugin-taskbar-wayland/resources/name-icon.match0000644000175000017500000001472314204636772023654 0ustar fengfengname=Apabi Reader ; icon=com.founder.apabi.reader name=斗鱼 ; icon=air.tv.douyu.android name=咪咕音乐 ; icon=cmccwm.mobilemusic name=新浪财经 ; icon=cn.; icon=com.sina.finance name=大麦 ; icon=cn.damai name=WPS ; icon=Office cn.wps.moffice_eng name=学习强国 ; icon=cn.xuexi.android name=铁路12306 ; icon=com.MobileTicket name=唯品会 ; icon=com.achievo.vipshop name=钉钉 ; icon=com.alibaba.android.rimet name=阿里云盘 ; icon=com.alicloud.databox name=百度网盘 ; icon=com.baidu.netdisk name=百度 ; icon=com.baidu.searchbox name=百度贴吧 ; icon=com.baidu.tieba name=菜鸟 ; icon=com.cainiao.wireless name=跳舞的线 ; icon=com.cmplay.dancingline name=汽车之家 ; icon=com.cubic.autohome name=每日瑜伽 ; icon=com.dailyyoga.cn name=大众点评 ; icon=com.dianping.v1 name=电视家 ; icon=com.dianshijia.tvlive name=豆瓣 ; icon=com.douban.frodo name=豆果美食 ; icon=com.douguo.recipe name=虎牙直播 ; icon=com.duowan.kiwi name=YY ; icon=com.duowan.mobile name=保卫萝卜3 ; icon=com.feiyu.carrot3 name=CAD看图王 ; icon=com.gstarmc.android name=开心消消乐® ; icon=com.happyelements.AndroidAnimal name=同花顺 ; icon=com.hexin.plat.android name=WeLink ; icon=com.huawei.welink name=芒果TV ; icon=com.hunantv.imgo.activity name=京东 ; icon=com.jingdong.app.mall name=前程无忧51job ; icon=com.job.android name=驾校一点通 ; icon=com.jxedt name=酷狗音乐 ; icon=com.kugou.android name=贝壳找房 ; icon=com.lianjia.beike name=蓝信+ ; icon=com.lite.lanxin name=流利说-英语 ; icon=com.liulishuo.engzo name=网易云音乐 ; icon=com.netease.cloudmusic name=网易邮箱 ; icon=com.netease.mobimail name=网易新闻 ; icon=com.netease.newsreader.activity name=向日葵远程控制 ; icon=com.oray.sunlogin name=我的汤姆猫 ; icon=com.outfit7.mytalkingtomfree name=汤姆猫跑酷 ; icon=com.outfit7.talkingtomgoldrun.wdj name=爱奇艺 ; icon=com.qiyi.video name=腾讯微云 ; icon=com.qq.qcloud name=欢乐麻将全集 ; icon=com.qqgame.happymj name=欢乐斗地主 ; icon=com.qqgame.hlddz name=美团 ; icon=com.sankuai.meituan name=网上国网 ; icon=com.sgcc.wsgw.cn name=得物(毒) ; icon=com.shizhuang.duapp name=新浪新闻 ; icon=com.sina.news name=绿洲 ; icon=com.sina.oasis name=微博 ; icon=com.sina.weibo name=快手 ; icon=com.smile.gifmaker name=今日头条 ; icon=com.ss.android.article.news name=西瓜视频 ; icon=com.ss.android.article.video name=懂车帝 ; icon=com.ss.android.auto name=抖音 ; icon=com.ss.android.ugc.aweme name=苏宁易购 ; icon=com.suning.mobile.ebuy name=皮皮虾 ; icon=com.sup.android.superb name=闲鱼 ; icon=com.taobao.idlefish name=飞猪旅行 ; icon=com.taobao.trip name=QQ邮箱 ; icon=com.tencent.androidqqmail name=腾讯课堂 ; icon=com.tencent.edu name=微信 ; icon=com.tencent.mm name=QQ ; icon=com.tencent.mobileqq name=QQ浏览器 ; icon=com.tencent.mtt name=腾讯新闻 ; icon=com.tencent.news name=天天爱消除 ; icon=com.tencent.peng name=欢乐升级 ; icon=com.tencent.qqgame.qqhlupwvga name=天天象棋 ; icon=com.tencent.qqgame.xq name=QQ极速版 ; icon=com.tencent.qqlite name=腾讯视频 ; icon=com.tencent.qqlive name=QQ音乐 ; icon=com.tencent.qqmusic name=腾讯体育 ; icon=com.tencent.qqsports name=和平精英 ; icon=com.tencent.tmgp.pubgmhd name=王者荣耀 ; icon=com.tencent.tmgp.sgame name=QQ飞车 ; icon=com.tencent.tmgp.speedmobile name=腾讯会议 ; icon=com.tencent.wemeet.app name=企业微信 ; icon=com.tencent.wework name=手机天猫 ; icon=com.tmall.wireless name=交管12123 ; icon=com.tmri.app.main name=航旅纵横 ; icon=com.umetrip.android.msky.app name=盒马 ; icon=com.wudaokou.hippo name=下厨房 ; icon=com.xiachufang name=香哈菜谱 ; icon=com.xiangha name=喜马拉雅 ; icon=com.ximalaya.ting.android name=小红书 ; icon=com.xingin.xhs name=迅雷 ; icon=com.xunlei.downloadprovider name=拼多多 ; icon=com.xunmeng.pinduoduo name=易车 ; icon=com.yiche.autoeasy name=印象笔记 ; icon=com.yinxiang name=网易有道词典 ; icon=com.youdao.dict name=有道云笔记 ; icon=com.youdao.note name=优酷视频 ; icon=com.youku.phone name=Gaaiho PDF ; icon=com.zeon.Gaaiho.Reader name=智联招聘 ; icon=com.zhaopin.social name=知乎 ; icon=com.zhihu.android name=携程旅行 ; icon=ctrip.android.view name=蜻蜓FM ; icon=fm.qingting.qtradio name=樊登读书 ; icon=io.dushu.fandengreader name=会见 ; iconorg.suirui.huijian.video name=哔哩哔哩 ; icon=tv.danmaku.bili name=i罗湖 ; icon=cn.gov.szlh.ilh name=福务通 ; icon=com.fdg.csp name=i深圳 ; icon=com.pingan.smt name=深圳天气 ; icon=com.sz.china.weather name=健康深圳 ; icon=com.xky.app.patient name=粤政易 ; icon=com.zwfw.YueZhengYi name=抖音极速版 ; icon=com.ss.android.ugc.aweme.lite name=今日头条极速版 ; icon=com.ss.android.article.lite name=快手极速版 ; icon=com.kuaishou.nebula name=百度极速版 ; icon=com.baidu.searchbox.lite name=爱奇艺极速版 ; icon=com.qiyi.video.lite name=喜马拉雅极速版 ; icon=com.ximalaya.ting.lite name=京东极速版 ; icon=com.jd.jdlite name=微博极速版 ; icon=com.sina.weibolite name=微博国际版 ; icon=com.weico.international name=贴吧极速版 ; icon=com.baidu.tieba_mini name=UC浏览器极速版 ; icon=com.ucmobile.lite name=斗鱼极速版 ; icon=com.douyu.rush name=皮皮虾极速版 ; icon=com.sup.android.slite name=驾考宝典极速版 icon=jiakaokesi.app.good name=驾校一点通极速版 ; icon=com.jxedtjsb name=汽车之家极速版 ; icon=com.autohome.speed name=易车极速版 ; icon=com.yiche.autofast name=央视影音 cn.cntv name=好信云会议 ; icon=com.lc.hx name=中国移动 ; icon=com.greenpoint.android.mc10086.activity name=中国联通 ; icon=com.sinovatech.unicom.ui name=中国建设银行 ; icon=com.chinamworld.main name=个人所得税 ; icon=cn.gov.tax.its name=手机天猫 ; icon=com.tmall.wireless name=美篇 ; icon=com.lanjingren.ivwen ukui-panel-3.0.6.4/plugin-taskbar-wayland/resources/taskbar.desktop.in0000644000175000017500000000026214204636772024410 0ustar fengfeng[Desktop Entry] Type=Service ServiceTypes=UKUIPanel/Plugin Name=Task manager Comment=Switch between running applications Icon=window-duplicate #TRANSLATIONS_DIR=../translations ukui-panel-3.0.6.4/plugin-taskbar-wayland/ukuitaskbar.h0000644000175000017500000002074714204636772021457 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2011 Razor team * 2014 LXQt team * Authors: * Alexander Sokoloff * Maciej Płaza * Kuzma Shapran * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef UKUITASKBAR_H #define UKUITASKBAR_H #include "../panel/iukuipanel.h" #include "../panel/iukuipanelplugin.h" #include "ukuitaskgroup.h" #include "ukuitaskbutton.h" #include #include #include //#include #include "../panel/iukuipanel.h" #include #include #include #include #include #include class QSignalMapper; class UKUITaskButton; class ElidedButtonStyle; class UKUITaskBarIcon; namespace UKUi { class GridLayout; } class UKUITaskBar : public QFrame { Q_OBJECT /* * 负责与ukui桌面环境应用通信的dbus * 在点击任务栏的时候发给其他UKUI DE APP 点击信号 * 以适应特殊的设计需求以及    */ Q_CLASSINFO("D-Bus Interface", "com.ukui.panel.plugins.taskbar") public: explicit UKUITaskBar(IUKUIPanelPlugin *plugin, QWidget* parent = 0); virtual ~UKUITaskBar(); /** * @brief realign * * it's use to realign the position of taskbar, the size and the position of taskgroup buttons and refresh the style of * * the icon in buttons. * */ void realign(); /** * @brief buttonStyle * * To get the style of the group buttons, the parameter in this class called mButtonStyle. * * @return Qt::ToolButtonStyle */ Qt::ToolButtonStyle buttonStyle() const { return mButtonStyle; } /** * @brief buttonWidth * * To get the width of the buttons, the parameter in this class called mButtonWidth. * * @return int */ int buttonWidth() const { return mButtonWidth; } /** * @brief closeOnMiddleClick * * To get the press of the mid-button on mouse, the parameter in this class called mCloseOnMiddleClick. * * @return bool */ bool closeOnMiddleClick() const { return mCloseOnMiddleClick; } /** * @brief raiseOnCurrentDesktop * * To get the window is on current desktop or not, to judge wether show the button. * * The parameter in this class called mRaiseOnCurrentDesktop. * * @return bool */ bool raiseOnCurrentDesktop() const { return mRaiseOnCurrentDesktop; } /** * @brief isShowOnlyOneDesktopTasks * * To get the group button contains just one window or more on one desktop. * * The parameter in this class called mShowOnlyOneDesktopTasks. * * @return bool */ bool isShowOnlyOneDesktopTasks() const { return mShowOnlyOneDesktopTasks; } /** * @brief showDesktopNum * * To get the number of the desktop which group buttons are showed. * * The parameter in this class called mshowDesktopNum. * * @return int */ int showDesktopNum() const { return mShowDesktopNum; } /** * @brief getCpuInfoFlg * * To get wether the type of the cpu is Loonson. * * @return */ bool getCpuInfoFlg() const { return CpuInfoFlg; } /** * @brief isShowOnlyCurrentScreenTasks * * To get wether the task window is only show on current screen. * * @return */ bool isShowOnlyCurrentScreenTasks() const { return mShowOnlyCurrentScreenTasks; } /** * @brief isShowOnlyMinimizedTasks * * To get wether the task window is only show in minimaized. * * @return */ bool isShowOnlyMinimizedTasks() const { return mShowOnlyMinimizedTasks; } /** * @brief isAutoRotate * * To get wether the auto rotation is on. * * @return */ bool isAutoRotate() const { return mAutoRotate; } /** * @brief isGroupingEnabled * * To get wether the window grouping is enable or not. * * @return */ bool isGroupingEnabled() const { return mGroupingEnabled; } /** * @brief isShowGroupOnHover * * To get wether the button is on hover by mouse or others. * * @return */ bool isShowGroupOnHover() const { return mShowGroupOnHover; } /** * @brief isIconByClass * * To get wether the group icon is in same class of the window or not. * * @return */ bool isIconByClass() const { return mIconByClass; } /** * @brief setShowGroupOnHover * * To set the flag of group button on hover. * * @param bFlag */ void setShowGroupOnHover(bool bFlag); inline IUKUIPanel * panel() const { return mPlugin->panel(); } inline IUKUIPanelPlugin * plugin() const { return mPlugin; } inline UKUITaskBarIcon* fetchIcon()const{return mpTaskBarIcon;} bool ignoreSymbolCMP(QString filename,QString groupname); signals: void buttonRotationRefreshed(bool autoRotate, IUKUIPanel::Position position); void buttonStyleRefreshed(Qt::ToolButtonStyle buttonStyle); void refreshIconGeometry(); void showOnlySettingChanged(); void iconByClassChanged(); void popupShown(UKUITaskGroup* sender); void sendToUkuiDEApp(void); protected: virtual void dragEnterEvent(QDragEnterEvent * event); virtual void dragMoveEvent(QDragMoveEvent * event); void enterEvent(QEvent *); void leaveEvent(QEvent *); void paintEvent(QPaintEvent *); void mousePressEvent(QMouseEvent *); private slots: void refreshTaskList(); void refreshButtonRotation(); void refreshPlaceholderVisibility(); void groupBecomeEmptySlot(); void onWindowChanged(WId window, NET::Properties prop, NET::Properties2 prop2); void onWindowAdded(WId window); void onWindowRemoved(WId window); void registerShortcuts(); void shortcutRegistered(); void activateTask(int pos); void wl_kwinSigHandler(quint32 wl_winId, int opNo, QString wl_iconName, QString wl_caption); private: typedef QMap windowMap_t; private: void addWindow(WId window); void addWindow_wl(QString iconName, QString caption, WId window); QHash matchAndroidIcon(); windowMap_t::iterator removeWindow(windowMap_t::iterator pos); void buttonMove(UKUITaskGroup * dst, UKUITaskGroup * src, QPoint const & pos); QString captionExchange(QString str); enum TaskStatus{NORMAL, HOVER, PRESS}; TaskStatus taskstatus; private: QMap mKnownWindows; //!< Ids of known windows (mapping to buttons/groups) QHash mAndroidIconHash; UKUi::GridLayout *mLayout; // QList mKeys; QSignalMapper *mSignalMapper; // Settings Qt::ToolButtonStyle mButtonStyle; int mButtonWidth; int mButtonHeight; bool CpuInfoFlg = true; bool mCloseOnMiddleClick; bool mRaiseOnCurrentDesktop; bool mShowOnlyOneDesktopTasks; int mShowDesktopNum; bool mShowOnlyCurrentScreenTasks; bool mShowOnlyMinimizedTasks; bool mAutoRotate; bool mGroupingEnabled; bool mShowGroupOnHover; bool mIconByClass; bool mCycleOnWheelScroll; //!< flag for processing the wheelEvent bool acceptWindow(WId window) const; void setButtonStyle(Qt::ToolButtonStyle buttonStyle); void settingsChanged(); void wheelEvent(QWheelEvent* event); void changeEvent(QEvent* event); void resizeEvent(QResizeEvent *event); IUKUIPanelPlugin *mPlugin; QWidget *mPlaceHolder; LeftAlignedTextStyle *mStyle; UKUITaskBarIcon *mpTaskBarIcon; QGSettings *changeTheme; }; #endif // UKUITASKBAR_H ukui-panel-3.0.6.4/plugin-taskbar-wayland/CMakeLists.txt0000644000175000017500000000230714204636772021511 0ustar fengfengset(PLUGIN "taskbar") set(HEADERS ukuitaskbar.h ukuitaskbutton.h ukuitaskbarplugin.h ukuitaskgroup.h ukuigrouppopup.h ukuitaskwidget.h ukuitaskclosebutton.h ukuitaskbaricon.h ) set(SOURCES ukuitaskbar.cpp ukuitaskbutton.cpp ukuitaskbarplugin.cpp ukuitaskgroup.cpp ukuigrouppopup.cpp ukuitaskwidget.cpp ukuitaskclosebutton.cpp ukuitaskbaricon.cpp ) find_package(X11 REQUIRED) set(LIBRARIES ${X11_LIBRARIES} Qt5X11Extras ) find_package(PkgConfig) pkg_check_modules(GIOUNIX2 REQUIRED gio-unix-2.0) pkg_check_modules(GLIB2 REQUIRED glib-2.0 gio-2.0) include_directories(${GLIB2_INCLUDE_DIRS}) #for include_directories(${_Qt5DBus_OWN_INCLUDE_DIRS}) include_directories( ${UKUI_INCLUDE_DIRS} "${CMAKE_CURRENT_SOURCE_DIR}/../panel" ${GIOUNIX2_INCLUDE_DIRS} ) set(LIBRARIES Qt5Xdg ${GIOUNIX2_LIBRARIES} ) install(FILES resources/name-icon.match DESTINATION "/usr/share/ukui/ukui-panel/plugin-taskbar" COMPONENT Runtime PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ GROUP_WRITE WORLD_READ WORLD_WRITE WORLD_EXECUTE GROUP_EXECUTE GROUP_READ ) BUILD_UKUI_PLUGIN(${PLUGIN}) ukui-panel-3.0.6.4/plugin-taskbar-wayland/ukuitaskbaricon.cpp0000644000175000017500000010230514204636772022652 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include #include //#include "ukuichineseletter.h" UKUITaskBarIcon::UKUITaskBarIcon() { // QString path=QDir::homePath()+"/.config/ukui/ukui-menu.ini"; // setting=new QSettings(path,QSettings::IniFormat); mMapFindDesktopByAppName.clear(); mMapFindIconByAppName.clear(); mMapFindExeByAppName.clear(); saveMapFromDeskptop(); } QVector UKUITaskBarIcon::appInfoVector=QVector(); QVector UKUITaskBarIcon::desktopfpVector=QVector(); QVector UKUITaskBarIcon::alphabeticVector=QVector(); QVector UKUITaskBarIcon::functionalVector=QVector(); QVector UKUITaskBarIcon::desktopAllVector=QVector(); QVector UKUITaskBarIcon::commonUseVector=QVector(); UKUITaskBarIcon::~UKUITaskBarIcon() { mMapFindDesktopByAppName.clear(); mMapFindIconByAppName.clear(); mMapFindExeByAppName.clear(); } //文件递归查询 void UKUITaskBarIcon::recursiveSearchFile(const QString& _filePath) { GError** error=nullptr; GKeyFileFlags flags=G_KEY_FILE_NONE; GKeyFile* keyfile=g_key_file_new (); QDir dir(_filePath); if (!dir.exists()) { return; } dir.setFilter(QDir::Dirs|QDir::Files|QDir::NoDotAndDotDot); dir.setSorting(QDir::DirsFirst); QFileInfoList list = dir.entryInfoList(); list.removeAll(QFileInfo("/usr/share/applications/screensavers")); if(list.size()< 1 ) { return; } int i=0; //递归算法的核心部分 do{ QFileInfo fileInfo = list.at(i); //如果是文件夹,递归 bool isDir = fileInfo.isDir(); if(isDir) { recursiveSearchFile(fileInfo.filePath()); } else{ //过滤后缀不是.desktop的文件 QString filePathStr=fileInfo.filePath(); QFileInfo fileinfo(filePathStr); QString file_suffix=fileinfo.suffix(); if(QString::compare(file_suffix,"desktop")!=0) { i++; continue; } QByteArray fpbyte=filePathStr.toLocal8Bit(); char* filepath=fpbyte.data(); g_key_file_load_from_file(keyfile,filepath,flags,error); char* ret_1=g_key_file_get_locale_string(keyfile,"Desktop Entry","NoDisplay", nullptr, nullptr); if(ret_1!=nullptr) { QString str=QString::fromLocal8Bit(ret_1); if(QString::compare(str, "true")==0) { i++; continue; } } //过滤LXQt、KDE char* ret=g_key_file_get_locale_string(keyfile,"Desktop Entry","OnlyShowIn", nullptr, nullptr); if(ret!=nullptr) { QString str=QString::fromLocal8Bit(ret); if(QString::compare(str, "LXQt;")==0 || QString::compare(str, "KDE;")==0) { i++; continue; } } //过滤中英文名为空的情况 QLocale cn; QString language=cn.languageToString(cn.language()); if(QString::compare(language,"Chinese")==0) { char* nameCh=g_key_file_get_string(keyfile,"Desktop Entry","Name[zh_CN]", nullptr); char* nameEn=g_key_file_get_string(keyfile,"Desktop Entry","Name", nullptr); if(QString::fromLocal8Bit(nameCh).isEmpty() && QString::fromLocal8Bit(nameEn).isEmpty()) { i++; free(nameCh); free(nameEn); continue; } free(nameCh); free(nameEn); } else { char* name=g_key_file_get_string(keyfile,"Desktop Entry","Name", nullptr); if(QString::fromLocal8Bit(name).isEmpty()) { i++; free(name); continue; } free(name); } filePathList.append(filePathStr); } i++; } while(i < list.size()); g_key_file_free(keyfile); } //获取系统deskyop文件路径 QStringList UKUITaskBarIcon::getDesktopFilePath() { filePathList.clear(); recursiveSearchFile("/usr/share/applications/"); filePathList.removeAll("/usr/share/applications/peony-folder-handler.desktop"); filePathList.removeAll("/usr/share/applications/gnome-software-local-file.desktop"); filePathList.removeAll("/usr/share/applications/org.gnome.Software.Editor.desktop"); filePathList.removeAll("/usr/share/applications/apport-gtk.desktop"); filePathList.removeAll("/usr/share/applications/software-properties-livepatch.desktop"); filePathList.removeAll("/usr/share/applications/snap-handle-link.desktop"); filePathList.removeAll("/usr/share/applications/python3.7.desktop"); filePathList.removeAll("/usr/share/applications/rhythmbox-device.desktop"); filePathList.removeAll("/usr/share/applications/smplayer_enqueue.desktop"); filePathList.removeAll("/usr/share/applications/python2.7.desktop"); filePathList.removeAll("/usr/share/applications/mate-color-select.desktop"); filePathList.removeAll("/usr/share/applications/shotwell-viewer.desktop"); filePathList.removeAll("/usr/share/applications/burner-nautilus.desktop"); filePathList.removeAll("/usr/share/applications/gnome-system-monitor-kde.desktop"); filePathList.removeAll("/usr/share/applications/hplj1020.desktop"); filePathList.removeAll("/usr/share/applications/ukui-network-scheme.desktop"); filePathList.removeAll("/usr/share/applications/ukui-panel.desktop"); filePathList.removeAll("/usr/share/applications/unity-activity-log-manager-panel.desktop"); filePathList.removeAll("/usr/share/applications/blueman-adapters.desktop"); filePathList.removeAll("/usr/share/applications/fcitx-config-gtk3.desktop"); filePathList.removeAll("/usr/share/applications/im-config.desktop"); filePathList.removeAll("/usr/share/applications/fcitx-skin-installer.desktop"); filePathList.removeAll("/usr/share/applications/gcr-prompter.desktop"); filePathList.removeAll("/usr/share/applications/gcr-viewer.desktop"); filePathList.removeAll("/usr/share/applications/geoclue-demo-agent.desktop"); filePathList.removeAll("/usr/share/applications/gnome-disk-image-mounter.desktop"); filePathList.removeAll("/usr/share/applications/gnome-disk-image-writer.desktop"); filePathList.removeAll("/usr/share/applications/libreoffice-xsltfilter.desktop"); filePathList.removeAll("/usr/share/applications/peony-autorun-software.desktop"); filePathList.removeAll("/usr/share/applications/remmina-file.desktop"); filePathList.removeAll("/usr/share/applications/remmina-gnome.desktop"); filePathList.removeAll("/usr/share/applications/ukwm.desktop"); filePathList.removeAll("/usr/share/applications/nm-applet.desktop"); filePathList.removeAll("/usr/share/applications/mate-user-guide.desktop"); filePathList.removeAll("/usr/share/applications/nm-connection-editor.desktop"); filePathList.removeAll("/usr/share/applications/pavucontrol-qt.desktop"); filePathList.removeAll("/usr/share/applications/ukui-volume-control.desktop"); filePathList.removeAll("/usr/share/applications/lximage-qt-screenshot.desktop"); filePathList.removeAll("/usr/share/applications/lximage-qt.desktop"); filePathList.removeAll("/usr/share/applications/appurl.desktop"); filePathList.removeAll("/usr/share/applications/debian-uxterm.desktop"); filePathList.removeAll("/usr/share/applications/debian-xterm.desktop"); filePathList.removeAll("/usr/share/applications/fcitx-ui-sogou-qimpanel.desktop"); filePathList.removeAll("/usr/share/applications/fcitx.desktop"); filePathList.removeAll("/usr/share/applications/fcitx-configtool.desktop"); filePathList.removeAll("/usr/share/applications/fcitx-qimpanel-configtool.desktop"); filePathList.removeAll("/usr/share/applications/peony-computer.desktop"); filePathList.removeAll("/usr/share/applications/onboard-settings.desktop"); filePathList.removeAll("/usr/share/applications/xscreensaver-properties.desktop"); filePathList.removeAll("/usr/share/applications/info.desktop"); filePathList.removeAll("/usr/share/applications/mate-about.desktop"); filePathList.removeAll("/usr/share/applications/pcmanfm-qt.desktop"); filePathList.removeAll("/usr/share/applications/qlipper.desktop"); filePathList.removeAll("/usr/share/applications/ktelnetservice5.desktop"); filePathList.removeAll("/usr/share/applications/ukui-power-preferences.desktop"); filePathList.removeAll("/usr/share/applications/ukui-power-statistics.desktop"); filePathList.removeAll("/usr/share/applications/software-properties-drivers.desktop"); filePathList.removeAll("/usr/share/applications/software-properties-gtk.desktop"); filePathList.removeAll("/usr/share/applications/galternatives.desktop"); filePathList.removeAll("/usr/share/applications/gnome-session-properties.desktop"); filePathList.removeAll("/usr/share/applications/pcmanfm-qt-desktop-pref.desktop"); filePathList.removeAll("/usr/share/applications/org.gnome.font-viewer.desktop"); filePathList.removeAll("/usr/share/applications/gucharmap.desktop"); filePathList.removeAll("/usr/share/applications/xdiagnose.desktop"); filePathList.removeAll("/usr/share/applications/gnome-language-selector.desktop"); filePathList.removeAll("/usr/share/applications/indicator-china-weather.desktop"); filePathList.removeAll("/usr/share/applications/mate-notification-properties.desktop"); filePathList.removeAll("/usr/share/applications/transmission-gtk.desktop"); filePathList.removeAll("/usr/share/applications/mpv.desktop"); filePathList.removeAll("/usr/share/applications/atril.desktop"); filePathList.removeAll("/usr/share/applications/org.kde.kwalletmanager5.desktop"); filePathList.removeAll("/usr/share/applications/system-config-printer.desktop"); filePathList.removeAll("/usr/share/applications/vim.desktop"); filePathList.removeAll("/usr/share/applications/kwalletmanager5-kwalletd.desktop"); filePathList.removeAll("/usr/share/applications/org.gnome.DejaDup.desktop"); filePathList.removeAll("/usr/share/applications/redshift.desktop"); filePathList.removeAll("/usr/share/applications/python3.8.desktop"); filePathList.removeAll("/usr/share/applications/yelp.desktop"); filePathList.removeAll("/usr/share/applications/peony-computer.desktop"); filePathList.removeAll("/usr/share/applications/peony-home.desktop"); filePathList.removeAll("/usr/share/applications/peony-trash.desktop"); filePathList.removeAll("/usr/share/applications/peony.desktop"); return filePathList; } void UKUITaskBarIcon::saveMapFromDeskptop() { QStringList desktopfpList=getDesktopFilePath(); for(int i=0;i::const_iterator it = mMapFindDesktopByAppName.find(_name); if(it != mMapFindDesktopByAppName.end()) { return it.value(); } else { return ""; } } QString UKUITaskBarIcon::getIconName(QString _name) { QMap::const_iterator it = mMapFindIconByAppName.find(_name); if(it != mMapFindIconByAppName.end()) { return it.value(); } else { return ""; } } QString UKUITaskBarIcon::getExeName(QString _name) { QMap::const_iterator it = mMapFindExeByAppName.find(_name); if(it != mMapFindExeByAppName.end()) { return it.value(); } else { return ""; } } //创建应用信息容器 QVector UKUITaskBarIcon::createAppInfoVector() { desktopfpVector.clear(); QVector appInfoVector; QVector vector; vector.append(QStringList()<<"Network");//1网络 vector.append(QStringList()<<"Messaging");//2社交 vector.append(QStringList()<<"Audio"<<"Video");//3影音 vector.append(QStringList()<<"Development");//4开发 vector.append(QStringList()<<"Graphics");//5图像 vector.append(QStringList()<<"Game");//6游戏 vector.append(QStringList()<<"Office"<<"Calculator"<<"Spreadsheet"<<"Presentation"<<"WordProcessor");//7办公 vector.append(QStringList()<<"Education");//8教育 vector.append(QStringList()<<"System"<<"Settings"<<"Security");//9系统 QStringList desktopfpList=getDesktopFilePath(); for(int i=0;i UKUITaskBarIcon::getAlphabeticClassification() { QVector data; QStringList appnameList; appnameList.clear(); QStringList list[27]; int index=0; while(index57 && c<65) || c>90) otherList.append(list[26].at(i)); else numberList.append(list[26].at(i)); } std::sort(otherList.begin(),otherList.end(),collator); std::sort(numberList.begin(),numberList.end(),collator); data.append(otherList); data.append(numberList); return data; } QVector UKUITaskBarIcon::getFunctionalClassification() { QStringList list[10]; int index=0; while(index data; data.clear(); // list[0].clear(); // list[0]=getRecentApp(); // data.append(list[0]); QLocale local; QString language=local.languageToString(local.language()); if(QString::compare(language,"Chinese")==0) local=QLocale(QLocale::Chinese); else local=QLocale(QLocale::English); QCollator collator(local); for(int i=0;i<10;i++) { std::sort(list[i].begin(),list[i].end(),collator); data.append(list[i]); } return data; } bool UKUITaskBarIcon::matchingAppCategories(QString desktopfp, QStringList categorylist) { QString category=getAppCategories(desktopfp); int index; for(index=0;indexbeginGroup("recentapp"); QStringList recentAppKeys=setting->allKeys(); for(int i=0;ivalue(recentAppKeys.at(i)).toInt())/nDaySec >= 3) setting->remove(recentAppKeys.at(i)); } setting->sync(); for(int i=0;iallKeys().size();i++) { QString desktopfp=QString("/usr/share/applications/"+setting->allKeys().at(i)); QFileInfo fileInfo(desktopfp); if(!fileInfo.exists()) continue; QString appname=getAppName(desktopfp); recentAppList.append(appname); } setting->endGroup(); QLocale local; QString language=local.languageToString(local.language()); if(QString::compare(language,"Chinese")==0) local=QLocale(QLocale::Chinese); else local=QLocale(QLocale::English); QCollator collator(local); std::sort(recentAppList.begin(),recentAppList.end(),collator); return recentAppList; } #endif QVector UKUITaskBarIcon::getDesktopAll() { QVector desktopAllVector; QVector commonVector; QStringList appNameList; desktopAllVector.clear(); commonVector.clear(); appNameList.clear(); // desktopAllVector=desktopfpVector; // commonVector=getCommonUseApp(); Q_FOREACH(QString desktopfp, desktopfpVector) { if(!commonVector.contains(desktopfp)) appNameList.append(getAppName(desktopfp)); } QLocale local; QString language=local.languageToString(local.language()); if(QString::compare(language,"Chinese")==0) local=QLocale(QLocale::Chinese); else local=QLocale(QLocale::English); QCollator collator(local); std::sort(appNameList.begin(),appNameList.end(),collator); Q_FOREACH(QString desktopfp, commonVector) desktopAllVector.append(desktopfp); Q_FOREACH(QString appName, appNameList) desktopAllVector.append(getDesktopPathByAppName(appName)); return desktopAllVector; } #if 0 QVector UKUITaskBarIcon::getCommonUseApp() { QDateTime dt=QDateTime::currentDateTime(); int currentDateTime=dt.toTime_t(); int nDaySec=24*60*60; setting->beginGroup("datetime"); QStringList dateTimeKeys=setting->allKeys(); QStringList timeOutKeys; timeOutKeys.clear(); for(int i=0;ivalue(dateTimeKeys.at(i)).toInt())/nDaySec >= 4) { timeOutKeys.append(dateTimeKeys.at(i)); } } setting->endGroup(); for(int i=0;ibeginGroup("application"); setting->remove(timeOutKeys.at(i)); setting->sync(); setting->endGroup(); setting->beginGroup("datetime"); setting->remove(timeOutKeys.at(i)); setting->sync(); setting->endGroup(); } setting->beginGroup("lockapplication"); QStringList lockdesktopfnList=setting->allKeys(); for(int i=0;ivalue(lockdesktopfnList.at(j)).toInt(); int value_2=setting->value(lockdesktopfnList.at(j+1)).toInt(); if(value_1 > value_2) { QString tmp=lockdesktopfnList.at(j); lockdesktopfnList.replace(j,lockdesktopfnList.at(j+1)); lockdesktopfnList.replace(j+1,tmp); } } setting->endGroup(); setting->beginGroup("application"); QStringList desktopfnList=setting->allKeys(); for(int i=0;ivalue(desktopfnList.at(j)).toInt(); int value_2=setting->value(desktopfnList.at(j+1)).toInt(); if(value_1 < value_2) { QString tmp=desktopfnList.at(j); desktopfnList.replace(j,desktopfnList.at(j+1)); desktopfnList.replace(j+1,tmp); } } setting->endGroup(); QVector data; Q_FOREACH(QString desktopfn,lockdesktopfnList) { QString desktopfp=QString("/usr/share/applications/"+desktopfn); QFileInfo fileInfo(desktopfp); if(!fileInfo.exists()) continue; data.append(desktopfp); } Q_FOREACH(QString desktopfn,desktopfnList) { QString desktopfp=QString("/usr/share/applications/"+desktopfn); QFileInfo fileInfo(desktopfp); if(!fileInfo.exists()) continue; data.append(desktopfp); } return data; } #endif //获取应用拼音 QString UKUITaskBarIcon::getAppNamePinyin(QString appname) { return ""/*UkuiChineseLetter::getPinyins(appname)*/; } //获取指定类型应用列表 QStringList UKUITaskBarIcon::getSpecifiedCategoryAppList(QString categorystr) { QByteArray categorybyte=categorystr.toLocal8Bit(); char* category=categorybyte.data(); QStringList desktopfpList=getDesktopFilePath(); QStringList appnameList; appnameList.clear(); for(int index=0;index(strlen(appcategory)-6); for(int i=0;i(getuid()); QDBusInterface iface("org.freedesktop.Accounts", "/org/freedesktop/Accounts", "org.freedesktop.Accounts", QDBusConnection::systemBus()); QDBusReplyobjPath=iface.call("FindUserById",uid); QDBusInterface useriface("org.freedesktop.Accounts", objPath.value().path(), "org.freedesktop.DBus.Properties", QDBusConnection::systemBus()); QDBusReply var=useriface.call("Get","org.freedesktop.Accounts.User","IconFile"); QString iconstr=var.value().toString(); return iconstr; } QString UKUITaskBarIcon::getUserName() { qint64 uid=static_cast(getuid()); // QString name=QDir::homePath(); QDBusInterface iface("org.freedesktop.Accounts", "/org/freedesktop/Accounts", "org.freedesktop.Accounts", QDBusConnection::systemBus()); QDBusReply objPath=iface.call("FindUserById",uid); QDBusInterface useriface("org.freedesktop.Accounts", objPath.value().path(), "org.freedesktop.DBus.Properties", QDBusConnection::systemBus()); QDBusReply var=useriface.call("Get","org.freedesktop.Accounts.User","UserName"); QString name=var.value().toString(); return name; } ukui-panel-3.0.6.4/plugin-taskbar-wayland/ukuitaskgroup.cpp0000644000175000017500000014530714204636772022402 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2011 Razor team * 2014 LXQt team * Authors: * Alexander Sokoloff * Maciej Płaza * Kuzma Shapran * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "ukuitaskgroup.h" #include "ukuitaskbar.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../panel/iukuipanelplugin.h" #include #include #include #include #include "../panel/customstyle.h" #define PREVIEW_WIDTH 468 #define PREVIEW_HEIGHT 428 #define SPACE_WIDTH 8 #define SPACE_HEIGHT 8 #define THUMBNAIL_WIDTH (PREVIEW_WIDTH - SPACE_WIDTH) #define THUMBNAIL_HEIGHT (PREVIEW_HEIGHT - SPACE_HEIGHT) #define ICON_WIDTH 48 #define ICON_HEIGHT 48 #define MAX_SIZE_OF_Thumb 16777215 #define SCREEN_MAX_WIDTH_SIZE 1400 #define SCREEN_MAX_HEIGHT_SIZE 1050 #define SCREEN_MIN_WIDTH_SIZE 800 #define SCREEN_MIN_HEIGHT_SIZE 600 #define SCREEN_MID_WIDTH_SIZE 1600 #define PREVIEW_WIDGET_MAX_WIDTH 352 #define PREVIEW_WIDGET_MAX_HEIGHT 264 #define PREVIEW_WIDGET_MIN_WIDTH 276 #define PREVIEW_WIDGET_MIN_HEIGHT 200 QPixmap qimageFromXImage(XImage* ximage) { QImage::Format format = QImage::Format_ARGB32_Premultiplied; if (ximage->depth == 24) format = QImage::Format_RGB32; else if (ximage->depth == 16) format = QImage::Format_RGB16; QImage image = QImage(reinterpret_cast(ximage->data), ximage->width, ximage->height, ximage->bytes_per_line, format).copy(); // 大端还是小端? if ((QSysInfo::ByteOrder == QSysInfo::LittleEndian && ximage->byte_order == MSBFirst) || (QSysInfo::ByteOrder == QSysInfo::BigEndian && ximage->byte_order == LSBFirst)) { for (int i = 0; i < image.height(); i++) { if (ximage->depth == 16) { ushort* p = reinterpret_cast(image.scanLine(i)); ushort* end = p + image.width(); while (p < end) { *p = ((*p << 8) & 0xff00) | ((*p >> 8) & 0x00ff); p++; } } else { uint* p = reinterpret_cast(image.scanLine(i)); uint* end = p + image.width(); while (p < end) { *p = ((*p << 24) & 0xff000000) | ((*p << 8) & 0x00ff0000) | ((*p >> 8) & 0x0000ff00) | ((*p >> 24) & 0x000000ff); p++; } } } } // 修复alpha通道 if (format == QImage::Format_RGB32) { QRgb* p = reinterpret_cast(image.bits()); for (int y = 0; y < ximage->height; ++y) { for (int x = 0; x < ximage->width; ++x) p[x] |= 0xff000000; p += ximage->bytes_per_line / 4; } } return QPixmap::fromImage(image); } /************************************************ ************************************************/ UKUITaskGroup::UKUITaskGroup(const QString &groupName, WId window, UKUITaskBar *parent) : UKUITaskButton(groupName,window, parent, parent), mGroupName(groupName), mPopup(new UKUIGroupPopup(this)), mPreventPopup(false), mSingleButton(true), mTimer(new QTimer(this)), mpWidget(NULL), isWaylandGroup(false) { Q_ASSERT(parent); mpScrollArea = NULL; taskgroupStatus = NORMAL; setObjectName(groupName); setText(groupName); initDesktopFileName(window); initActionsInRightButtonMenu(); connect(this, SIGNAL(clicked(bool)), this, SLOT(onClicked(bool))); connect(KWindowSystem::self(), SIGNAL(currentDesktopChanged(int)), this, SLOT(onDesktopChanged(int))); connect(KWindowSystem::self(), SIGNAL(activeWindowChanged(WId)), this, SLOT(onActiveWindowChanged(WId))); connect(parent, &UKUITaskBar::refreshIconGeometry, this, &UKUITaskGroup::refreshIconsGeometry); connect(parent, &UKUITaskBar::buttonStyleRefreshed, this, &UKUITaskGroup::setToolButtonsStyle); connect(parent, &UKUITaskBar::showOnlySettingChanged, this, &UKUITaskGroup::refreshVisibility); connect(parent, &UKUITaskBar::popupShown, this, &UKUITaskGroup::groupPopupShown); mTimer->setTimerType(Qt::PreciseTimer); connect(mTimer, SIGNAL(timeout()), SLOT(timeout())); } UKUITaskGroup::UKUITaskGroup(const QString & iconName, const QString & caption, WId window, UKUITaskBar *parent) : UKUITaskButton(iconName, caption, window, parent, parent), mTimer(new QTimer(this)), mPopup(new UKUIGroupPopup(this)), mPreventPopup(false), mpWidget(NULL), mSingleButton(false), isWaylandGroup(true) { //setObjectName(caption); //setText(caption); Q_ASSERT(parent); mIconName=iconName; taskgroupStatus = NORMAL; isWinActivate = true; setIcon(QIcon::fromTheme(iconName)); connect(this, SIGNAL(clicked(bool)), this, SLOT(onClicked(bool))); connect(parent, &UKUITaskBar::buttonStyleRefreshed, this, &UKUITaskGroup::setToolButtonsStyle); //connect(parent, &UKUITaskBar::showOnlySettingChanged, this, &UKUITaskGroup::refreshVisibility); connect(parent, &UKUITaskBar::popupShown, this, &UKUITaskGroup::groupPopupShown); mTimer->setTimerType(Qt::PreciseTimer); connect(mTimer, SIGNAL(timeout()), SLOT(timeout())); } UKUITaskGroup::~UKUITaskGroup() { // if(mPopup) // { // mPopup->deleteLater(); // mPopup = NULL; // } // if(mpWidget) // { // mpWidget->deleteLater(); // mpWidget = NULL; // } // if(VLayout) // { // VLayout->deleteLater(); // VLayout = NULL; // } } void UKUITaskGroup::wl_widgetUpdateTitle(QString caption) { if (caption.isNull()) return; for (UKUITaskWidget *button : qAsConst(mButtonHash) ) button->wl_updateTitle(caption); } bool DesktopFileNameCompare(QString str1, QString str2) { if (str1 == str2) return true; if (str2.contains(str1)) return true; if (str1.contains(str2)) return true; return false; } QString getDesktopFileName(QString cmd) { char name[200]; FILE *fp1 = NULL; if ((fp1 = popen(cmd.toStdString().data(), "r")) == NULL) return QString(); memset(name, 0, sizeof(name)); fgets(name, sizeof(name),fp1); pclose(fp1); return QString(name); } void UKUITaskGroup::badBackFunctionToFindDesktop() { if (file_name.isEmpty()) { QDir dir("/usr/share/applications/"); QFileInfoList list = dir.entryInfoList(); for (int i = 0; i < list.size(); i++) { QFileInfo fileInfo = list.at(i); if (parentTaskBar()->ignoreSymbolCMP(fileInfo.filePath(), groupName())) { file_name = fileInfo.filePath(); if (file_name == QString(PEONY_COMUTER) || file_name == QString(PEONY_TRASH) || file_name == QString(PEONY_HOME)) file_name = QString(PEONY_MAIN); break; } } } } void UKUITaskGroup::initDesktopFileName(WId window) { KWindowInfo info(window, 0, NET::WM2DesktopFileName); QString cmd; cmd.sprintf(GET_PROCESS_EXEC_NAME_MAIN, info.pid()); QString processExeName = getDesktopFileName(cmd); QDir dir(DEKSTOP_FILE_PATH); QFileInfoList list = dir.entryInfoList(); for (int i = 0; i < list.size(); i++) { bool flag = false; QFileInfo fileInfo = list.at(i); QString _cmd; if (fileInfo.filePath() == QString(USR_SHARE_APP_CURRENT) || fileInfo.filePath() == QString(USR_SHARE_APP_UPER) ) continue; _cmd.sprintf(GET_DESKTOP_EXEC_NAME_MAIN, fileInfo.filePath().toStdString().data()); QString desktopFileExeName = getDesktopFileName(_cmd); flag = DesktopFileNameCompare(desktopFileExeName, processExeName); if (flag && !desktopFileExeName.isEmpty()) { file_name = fileInfo.filePath(); if (file_name == QString(PEONY_COMUTER) || file_name == QString(PEONY_TRASH) || file_name == QString(PEONY_HOME) ) file_name = QString(PEONY_MAIN); break; } } if (file_name.isEmpty()) { for (int i = 0; i < list.size(); i++) { bool flag = false; QFileInfo fileInfo = list.at(i); if (fileInfo.filePath() == QString(USR_SHARE_APP_CURRENT) || fileInfo.filePath() == QString(USR_SHARE_APP_UPER) ) continue; QString _cmd; _cmd.sprintf(GET_DESKTOP_EXEC_NAME_BACK, fileInfo.filePath().toStdString().data()); QString desktopFileExeName = getDesktopFileName(_cmd); flag = DesktopFileNameCompare(desktopFileExeName, processExeName); if (flag && !desktopFileExeName.isEmpty()) { file_name = fileInfo.filePath(); if (file_name == QString(PEONY_COMUTER) || file_name == QString(PEONY_TRASH) || file_name == QString(PEONY_HOME) ) file_name = QString(PEONY_MAIN); break; } } } badBackFunctionToFindDesktop(); } void UKUITaskGroup::initActionsInRightButtonMenu(){ if (file_name.isEmpty()) return; const auto url=QUrl(file_name); QString fileName(url.isLocalFile() ? url.toLocalFile() : url.url()); QFileInfo fi(fileName); XdgDesktopFile xdg; if (xdg.load(fileName)) { /*This fuction returns true if the desktop file is applicable to the current environment. but I don't need this attributes now */ // if (xdg.isSuitable()) mAct = new QuickLaunchAction(&xdg, this); } else if (fi.exists() && fi.isExecutable() && !fi.isDir()) { mAct = new QuickLaunchAction(fileName, fileName, "", this); } else if (fi.exists()) { mAct = new QuickLaunchAction(fileName, this); } setGroupIcon(mAct->getIconfromAction()); } /************************************************ ************************************************/ void UKUITaskGroup::contextMenuEvent(QContextMenuEvent *event) { setPopupVisible(false, true); mPreventPopup = true; if (mSingleButton && !isWaylandGroup) { UKUITaskButton::contextMenuEvent(event); return; } QMenu * menu = new QMenu(tr("Group")); menu->setAttribute(Qt::WA_DeleteOnClose); QAction *close = menu->addAction(QIcon::fromTheme("window-close-symbolic"), tr("close")); connect(close, SIGNAL(triggered()), this, SLOT(closeGroup())); connect(menu, &QMenu::aboutToHide, [this] { mPreventPopup = false; }); menu->setGeometry(plugin()->panel()->calculatePopupWindowPos(mapToGlobal(event->pos()), menu->sizeHint())); plugin()->willShowWindow(menu); menu->show(); } /************************************************ ************************************************/ void UKUITaskGroup::closeGroup_wl() { QDBusMessage message = QDBusMessage::createSignal("/", "com.ukui.kwin", "request"); QList args; quint32 m_wid=windowId(); args.append(m_wid); args.append(WAYLAND_GROUP_CLOSE); message.setArguments(args); QDBusConnection::sessionBus().send(message); } void UKUITaskGroup::closeGroup() { if (isWaylandGroup) { closeGroup_wl(); return; } //To Do #if (QT_VERSION < QT_VERSION_CHECK(5,7,0)) for(auto it=mButtonHash.begin();it!=mButtonHash.end();it++) { UKUITaskWidget *button =it.value(); if (button->isOnDesktop(KWindowSystem::currentDesktop())) button->closeApplication(); } #else for (UKUITaskWidget *button : qAsConst(mButtonHash) ) if (button->isOnDesktop(KWindowSystem::currentDesktop())) button->minimizeApplication(); for (UKUITaskWidget *button : qAsConst(mButtonHash) ) if (button->isOnDesktop(KWindowSystem::currentDesktop())) button->closeApplication(); #endif } /************************************************ ************************************************/ QWidget * UKUITaskGroup::wl_addWindow(WId id) { if (mButtonHash.contains(id)) return mButtonHash.value(id); UKUITaskWidget *btn; if (isWaylandGroup) { btn = new UKUITaskWidget(QString("kyiln-video"), id, parentTaskBar(), mPopup); mButtonHash.insert(id, btn); return btn; } else btn = new UKUITaskWidget(id, parentTaskBar(), mPopup); mButtonHash.insert(id, btn); connect(btn, SIGNAL(clicked()), this, SLOT(onClicked(bool))); connect(btn, SIGNAL(windowMaximize()), this, SLOT(onChildButtonClicked())); this->setStyle(new CustomStyle("taskbutton",true)); return btn; } QWidget * UKUITaskGroup::addWindow(WId id) { if (mButtonHash.contains(id)) return mButtonHash.value(id); UKUITaskWidget *btn; btn = new UKUITaskWidget(id, parentTaskBar(), mPopup); mButtonHash.insert(id, btn); connect(btn, SIGNAL(clicked()), this, SLOT(onChildButtonClicked())); connect(btn, SIGNAL(windowMaximize()), this, SLOT(onChildButtonClicked())); refreshVisibility(); changeTaskButtonStyle(); return btn; } /************************************************ ************************************************/ QWidget * UKUITaskGroup::checkedButton() const { // for (QWidget* button : qAsConst(mButtonHash)) // if (button->isChecked()) // return button; return NULL; } /*changeTaskButtonStyle in class UKUITaskGroup not class UKUITaskButton * because class UKUITaskButton can not get mButtonHash.size */ void UKUITaskGroup::changeTaskButtonStyle() { if(mVisibleHash.size()>1) this->setStyle(new CustomStyle("taskbutton",true)); else this->setStyle(new CustomStyle("taskbutton",false)); } /************************************************ ************************************************/ QWidget * UKUITaskGroup::getNextPrevChildButton(bool next, bool circular) { #if 0 QWidget *button = checkedButton(); int idx = mPopup->indexOf(button); int inc = next ? 1 : -1; idx += inc; // if there is no cheked button, get the first one if next equals true // or the last one if not if (!button) { idx = -1; if (next) { for (int i = 0; i < mPopup->count() && idx == -1; i++) if (mPopup->itemAt(i)->widget()->isVisibleTo(mPopup)) idx = i; } else { for (int i = mPopup->count() - 1; i >= 0 && idx == -1; i--) if (mPopup->itemAt(i)->widget()->isVisibleTo(mPopup)) idx = i; } } if (circular) idx = (idx + mButtonHash.count()) % mButtonHash.count(); else if (mPopup->count() <= idx || idx < 0) return NULL; // return the next or the previous child QLayoutItem *item = mPopup->itemAt(idx); if (item) { button = qobject_cast(item->widget()); if (button->isVisibleTo(mPopup)) return button; } #endif return NULL; } /************************************************ ************************************************/ void UKUITaskGroup::onActiveWindowChanged(WId window) { UKUITaskWidget *button = mButtonHash.value(window, nullptr); // for (QWidget *btn : qAsConst(mButtonHash)) // btn->setChecked(false); // if (button) // { // button->setChecked(true); // if (button->hasUrgencyHint()) // button->setUrgencyHint(false); // } setChecked(nullptr != button); } /************************************************ ************************************************/ void UKUITaskGroup::onDesktopChanged(int number) { refreshVisibility(); changeTaskButtonStyle(); } /************************************************ ************************************************/ void UKUITaskGroup::onWindowRemoved(WId window) { if (mButtonHash.contains(window)) { UKUITaskWidget *button = mButtonHash.value(window); mButtonHash.remove(window); if (mVisibleHash.contains(window)) mVisibleHash.remove(window); mPopup->removeWidget(button); button->deleteLater(); if (!parentTaskBar()->getCpuInfoFlg()) system(QString("rm -f /tmp/%1.png").arg(window).toLatin1()); if (isLeaderWindow(window)) setLeaderWindow(mButtonHash.begin().key()); if (mButtonHash.count()) { if(mPopup->isVisible()) { // mPopup->hide(true); showPreview(); } else { regroup(); } } else { if (isVisible()) emit visibilityChanged(false); hide(); emit groupBecomeEmpty(groupName()); } changeTaskButtonStyle(); } } /************************************************ ************************************************/ void UKUITaskGroup::onChildButtonClicked() { setPopupVisible(false, true); parentTaskBar()->setShowGroupOnHover(true); //QToolButton::leaveEvent(event); taskgroupStatus = NORMAL; update(); } /************************************************ ************************************************/ Qt::ToolButtonStyle UKUITaskGroup::popupButtonStyle() const { // do not set icons-only style in the buttons in the group, // as they'll be indistinguishable const Qt::ToolButtonStyle style = toolButtonStyle(); return style == Qt::ToolButtonIconOnly ? Qt::ToolButtonTextBesideIcon : style; } /************************************************ ************************************************/ void UKUITaskGroup::setToolButtonsStyle(Qt::ToolButtonStyle style) { setToolButtonStyle(style); // const Qt::ToolButtonStyle styleInPopup = popupButtonStyle(); // for (auto & button : mButtonHash) // { // button->setToolButtonStyle(styleInPopup); // } } /************************************************ ************************************************/ int UKUITaskGroup::buttonsCount() const { return mButtonHash.count(); } void UKUITaskGroup::initVisibleHash() { /* for (UKUITaskButtonHash::const_iterator it = mButtonHash.begin();it != mButtonHash.end();it++) { if (mVisibleHash.contains(it.key())) continue; if (it.value()->isVisibleTo(mPopup)) mVisibleHash.insert(it.key(), it.value()); }*/ } /************************************************ ************************************************/ int UKUITaskGroup::visibleButtonsCount() const { int i = 0; #if (QT_VERSION < QT_VERSION_CHECK(5,7,0)) for (auto it=mButtonHash.begin();it!=mButtonHash.end();it++) { UKUITaskWidget *btn=it.value(); if (btn->isVisibleTo(mPopup)) i++; } #else for (UKUITaskWidget *btn : qAsConst(mButtonHash)) if (btn->isVisibleTo(mPopup)) i++; #endif return i; } /************************************************ ************************************************/ void UKUITaskGroup::draggingTimerTimeout() { if (mSingleButton) setPopupVisible(false); } /************************************************ ************************************************/ void UKUITaskGroup::setActivateState_wl(bool _state) { isWinActivate = _state; taskgroupStatus = (_state ? HOVER : NORMAL); repaint(); } void UKUITaskGroup::winClickActivate_wl(bool _getActive) { QDBusMessage message = QDBusMessage::createSignal("/", "com.ukui.kwin", "request"); QList args; quint32 m_wid=windowId(); args.append(m_wid); args.append((_getActive ? WAYLAND_GROUP_ACTIVATE : WAYLAND_GROUP_HIDE)); isWinActivate = _getActive; taskgroupStatus = (_getActive ? HOVER : NORMAL); repaint(); message.setArguments(args); QDBusConnection::sessionBus().send(message); } void UKUITaskGroup::onClicked(bool) { if (isWaylandGroup) { winClickActivate_wl(!isWinActivate); return; } if (1 == mVisibleHash.size()) { singleWindowClick(); return; } if(mPopup->isVisible()) { if(HOVER == taskgroupStatus) { taskgroupStatus = NORMAL; return; } else { mPopup->hide(); return; } } else { showPreview(); } mTaskGroupEvent = OTHEREVENT; if(mTimer->isActive()) { mTimer->stop(); } } void UKUITaskGroup::singleWindowClick() { UKUITaskWidget *btn = mVisibleHash.value(windowId()); if(btn) { if(btn->isMinimized() || KWindowSystem::showingDesktop()) { if(mPopup->isVisible()) { mPopup->hide(); } KWindowSystem::activateWindow(windowId()); } else { btn->minimizeApplication(); if(mPopup->isVisible()) { mPopup->hide(); } } } mTaskGroupEvent = OTHEREVENT; if(mTimer->isActive()) { mTimer->stop(); } } /************************************************ ************************************************/ void UKUITaskGroup::regroup() { int cont = visibleButtonsCount(); recalculateFrameIfVisible(); // if (cont == 1) // { // mSingleButton = false; // // Get first visible button // UKUITaskButton * button = NULL; // for (UKUITaskButton *btn : qAsConst(mButtonHash)) // { // if (btn->isVisibleTo(mPopup)) // { // button = btn; // break; // } // } // if (button) // { // setText(button->text()); // setToolTip(button->toolTip()); // setWindowId(button->windowId()); // } // } /*else*/ if (cont == 0) hide(); else { mSingleButton = false; QString t = QString("%1 - %2 windows").arg(mGroupName).arg(cont); setText(t); setToolTip(parentTaskBar()->isShowGroupOnHover() ? QString() : t); } } /************************************************ ************************************************/ void UKUITaskGroup::recalculateFrameIfVisible() { if (mPopup->isVisible()) { recalculateFrameSize(); if (plugin()->panel()->position() == IUKUIPanel::PositionBottom) recalculateFramePosition(); } } /************************************************ ************************************************/ void UKUITaskGroup::setAutoRotation(bool value, IUKUIPanel::Position position) { // for (QWidget *button : qAsConst(mButtonHash)) // button->setAutoRotation(false, position); //UKUITaskWidget::setAutoRotation(value, position); } /************************************************ ************************************************/ void UKUITaskGroup::refreshVisibility() { bool will = false; UKUITaskBar const * taskbar = parentTaskBar(); const int showDesktop = taskbar->showDesktopNum(); for(UKUITaskButtonHash::const_iterator i=mButtonHash.begin();i!=mButtonHash.end();i++) { UKUITaskWidget * btn=i.value(); bool visible = taskbar->isShowOnlyOneDesktopTasks() ? btn->isOnDesktop(0 == showDesktop ? KWindowSystem::currentDesktop() : showDesktop) : true; visible &= taskbar->isShowOnlyCurrentScreenTasks() ? btn->isOnCurrentScreen() : true; visible &= taskbar->isShowOnlyMinimizedTasks() ? btn->isMinimized() : true; btn->setVisible(visible); if (btn->isVisibleTo(mPopup) && !mVisibleHash.contains(i.key())) mVisibleHash.insert(i.key(), i.value()); else if (!btn->isVisibleTo(mPopup) && mVisibleHash.contains(i.key())) { mVisibleHash.remove(i.key()); if (isLeaderWindow(btn->windowId()) && !will) { setLeaderWindow(btn->windowId()); } } will |= visible; } bool is = isVisible(); setVisible(will); if(!mPopup->isVisible()) { regroup(); } if (is != will) emit visibilityChanged(will); } /************************************************ ************************************************/ QMimeData * UKUITaskGroup::mimeData() { QMimeData *mimedata = new QMimeData; QByteArray byteArray; QDataStream stream(&byteArray, QIODevice::WriteOnly); stream << groupName(); mimedata->setData(mimeDataFormat(), byteArray); return mimedata; } /************************************************ ************************************************/ void UKUITaskGroup::setPopupVisible(bool visible, bool fast) { if (visible && !mPreventPopup && !mSingleButton) { // QTimer::singleShot(400, this,SLOT(showPreview())); showPreview(); /* for origin preview plugin()->willShowWindow(mPopup); mPopup->show(); qDebug()<<"setPopupVisible ********"; emit popupShown(this);*/ } else mPopup->hide(fast); } /************************************************ ************************************************/ void UKUITaskGroup::refreshIconsGeometry() { QRect rect = geometry(); rect.moveTo(mapToGlobal(QPoint(0, 0))); if (mSingleButton) { refreshIconGeometry(rect); return; } // for(UKUITaskButton *but : qAsConst(mButtonHash)) // { // but->refreshIconGeometry(rect); // but->setIconSize(QSize(plugin()->panel()->iconSize(), plugin()->panel()->iconSize())); // } } /************************************************ ************************************************/ QSize UKUITaskGroup::recalculateFrameSize() { int height = recalculateFrameHeight(); mPopup->setMaximumHeight(1000); mPopup->setMinimumHeight(0); int hh = recalculateFrameWidth(); mPopup->setMaximumWidth(hh); mPopup->setMinimumWidth(0); QSize newSize(hh, height); mPopup->resize(newSize); return newSize; } /************************************************ ************************************************/ int UKUITaskGroup::recalculateFrameHeight() const { // int cont = visibleButtonsCount(); // int h = !plugin()->panel()->isHorizontal() && parentTaskBar()->isAutoRotate() ? width() : height(); // return cont * h + (cont + 1) * mPopup->spacing(); return 120; } /************************************************ ************************************************/ int UKUITaskGroup::recalculateFrameWidth() const { const QFontMetrics fm = fontMetrics(); int max = 100 * fm.width (' '); // elide after the max width int txtWidth = 0; // for (UKUITaskButton *btn : qAsConst(mButtonHash)) // txtWidth = qMax(fm.width(btn->text()), txtWidth); return iconSize().width() + qMin(txtWidth, max) + 30/* give enough room to margins and borders*/; } /************************************************ ************************************************/ QPoint UKUITaskGroup::recalculateFramePosition() { // Set position int x_offset = 0, y_offset = 0; switch (plugin()->panel()->position()) { case IUKUIPanel::PositionTop: y_offset += height(); break; case IUKUIPanel::PositionBottom: y_offset = -recalculateFrameHeight(); break; case IUKUIPanel::PositionLeft: x_offset += width(); break; case IUKUIPanel::PositionRight: x_offset = -recalculateFrameWidth(); break; } QPoint pos = mapToGlobal(QPoint(x_offset, y_offset)); mPopup->move(pos); return pos; } /************************************************ ************************************************/ void UKUITaskGroup::leaveEvent(QEvent *event) { //QTimer::singleShot(300, this,SLOT(mouseLeaveOut())); mTaskGroupEvent = LEAVEEVENT; mEvent = event; if(mTimer->isActive()) { mTimer->stop();//stay time is no more than 400 ms need kill timer } else { mTimer->start(300); } } /************************************************ ************************************************/ void UKUITaskGroup::enterEvent(QEvent *event) { //QToolButton::enterEvent(event); mTaskGroupEvent = ENTEREVENT; mEvent = event; mTimer->start(400); // if (sDraggging) // return; // if (parentTaskBar()->isShowGroupOnHover()) // { // setPopupVisible(true); // parentTaskBar()->setShowGroupOnHover(false);//enter this group other groups will be blocked // } // taskgroupStatus = HOVER; // repaint(); } void UKUITaskGroup::handleSavedEvent() { if (sDraggging) return; if (parentTaskBar()->isShowGroupOnHover()) { setPopupVisible(true); } taskgroupStatus = HOVER; repaint(); QToolButton::enterEvent(mEvent); } //void UKUITaskGroup::paintEvent(QPaintEvent *) //{ //} /************************************************ ************************************************/ void UKUITaskGroup::dragEnterEvent(QDragEnterEvent *event) { // only show the popup if we aren't dragging a taskgroup if (!event->mimeData()->hasFormat(mimeDataFormat())) { setPopupVisible(true); } UKUITaskButton::dragEnterEvent(event); } /************************************************ ************************************************/ void UKUITaskGroup::dragLeaveEvent(QDragLeaveEvent *event) { // if draggind something into the taskgroup or the taskgroups' popup, // do not close the popup if (!sDraggging) setPopupVisible(false); UKUITaskButton::dragLeaveEvent(event); } void UKUITaskGroup::mouseMoveEvent(QMouseEvent* event) { // if dragging the taskgroup, do not show the popup setPopupVisible(false, true); UKUITaskButton::mouseMoveEvent(event); } /************************************************ ************************************************/ bool UKUITaskGroup::onWindowChanged(WId window, NET::Properties prop, NET::Properties2 prop2) { // returns true if the class is preserved bool needsRefreshVisibility{false}; QVector buttons; if (mButtonHash.contains(window)) buttons.append(mButtonHash.value(window)); // If group is based on that window properties must be changed also on button group if (window == windowId()) buttons.append(this); if (!buttons.isEmpty()) { // if class is changed the window won't belong to our group any more if (parentTaskBar()->isGroupingEnabled() && prop2.testFlag(NET::WM2WindowClass)) { KWindowInfo info(window, 0, NET::WM2WindowClass); if (info.windowClassClass() != mGroupName) { onWindowRemoved(window); return false; } } // window changed virtual desktop if (prop.testFlag(NET::WMDesktop) || prop.testFlag(NET::WMGeometry)) { if (parentTaskBar()->isShowOnlyOneDesktopTasks() || parentTaskBar()->isShowOnlyCurrentScreenTasks()) { needsRefreshVisibility = true; } } // if (prop.testFlag(NET::WMVisibleName) || prop.testFlag(NET::WMName)) // std::for_each(buttons.begin(), buttons.end(), std::mem_fn(&UKUITaskButton::updateText)); // XXX: we are setting window icon geometry -> don't need to handle NET::WMIconGeometry // Icon of the button can be based on windowClass // if (prop.testFlag(NET::WMIcon) || prop2.testFlag(NET::WM2WindowClass)) // std::for_each(buttons.begin(), buttons.end(), std::mem_fn(&UKUITaskButton::updateIcon)); if (prop.testFlag(NET::WMState)) { KWindowInfo info{window, NET::WMState}; if (info.hasState(NET::SkipTaskbar)) onWindowRemoved(window); // std::for_each(buttons.begin(), buttons.end(), std::bind(&UKUITaskButton::setUrgencyHint, std::placeholders::_1, info.hasState(NET::DemandsAttention))); if (parentTaskBar()->isShowOnlyMinimizedTasks()) { needsRefreshVisibility = true; } } } if (needsRefreshVisibility) refreshVisibility(); return true; } /************************************************ ************************************************/ void UKUITaskGroup::groupPopupShown(UKUITaskGroup * const sender) { //close all popups (should they be visible because of close delay) if (this != sender && isVisible()) setPopupVisible(false, true/*fast*/); } void UKUITaskGroup::removeWidget() { if(mpScrollArea) { removeSrollWidget(); } if(mpWidget) { mPopup->layout()->removeWidget(mpWidget); QHBoxLayout *hLayout = dynamic_cast(mpWidget->layout()); QVBoxLayout *vLayout = dynamic_cast(mpWidget->layout()); if(hLayout != NULL) { hLayout->deleteLater(); hLayout = NULL; } if(vLayout != NULL) { vLayout->deleteLater(); vLayout = NULL; } //mpWidget->setParent(NULL); mpWidget->deleteLater(); mpWidget = NULL; } } void UKUITaskGroup::removeSrollWidget() { if(mpScrollArea) { mPopup->layout()->removeWidget(mpScrollArea); mPopup->layout()->removeWidget(mpScrollArea->takeWidget()); } if(mpWidget) { mPopup->layout()->removeWidget(mpWidget); QHBoxLayout *hLayout = dynamic_cast(mpWidget->layout()); QVBoxLayout *vLayout = dynamic_cast(mpWidget->layout()); if(hLayout != NULL) { hLayout->deleteLater(); hLayout = NULL; } if(vLayout != NULL) { vLayout->deleteLater(); vLayout = NULL; } //mpWidget->setParent(NULL); mpWidget->deleteLater(); mpWidget = NULL; } if(mpScrollArea) { mpScrollArea->deleteLater(); mpScrollArea = NULL; } } void UKUITaskGroup::setLayOutForPostion() { if(mVisibleHash.size() > 10)//more than 10 need { mpWidget->setLayout(new QVBoxLayout); mpWidget->layout()->setAlignment(Qt::AlignTop); mpWidget->layout()->setSpacing(3); mpWidget->layout()->setMargin(3); return; } if(plugin()->panel()->isHorizontal()) { mpWidget->setLayout(new QHBoxLayout); mpWidget->layout()->setSpacing(3); mpWidget->layout()->setMargin(3); } else { mpWidget->setLayout(new QVBoxLayout); mpWidget->layout()->setSpacing(3); mpWidget->layout()->setMargin(3); } } bool UKUITaskGroup::isSetMaxWindow() { int iScreenWidth = QApplication::screens().at(0)->size().width(); int iScreenHeight = QApplication::screens().at(0)->size().height(); if((iScreenWidth >= SCREEN_MID_WIDTH_SIZE)||((iScreenWidth > SCREEN_MAX_WIDTH_SIZE) && (iScreenHeight > SCREEN_MAX_HEIGHT_SIZE))) { return true; } else { return false; } } void UKUITaskGroup::showPreview() { int n = 7; if (plugin()->panel()->isHorizontal()) n = 10; if(mVisibleHash.size() <= n) { showAllWindowByThumbnail(); } else { showAllWindowByList(); } } void UKUITaskGroup::adjustPopWindowSize(int winWidth, int winHeight) { int size = mVisibleHash.size(); if (isWaylandGroup) size = 1; if(plugin()->panel()->isHorizontal()) { mPopup->setFixedSize(winWidth*size + (size + 1)*3, winHeight + 6); } else { mPopup->setFixedSize(winWidth + 6,winHeight*size + (size + 1)*3); } mPopup->adjustSize(); } void UKUITaskGroup::v_adjustPopWindowSize(int winWidth, int winHeight, int v_all) { int fixed_size = v_all; if(plugin()->panel()->isHorizontal()) { int iScreenWidth = QApplication::screens().at(0)->size().width(); if (fixed_size > iScreenWidth) fixed_size = iScreenWidth; mPopup->setFixedSize(fixed_size, winHeight + 6); } else { int iScreenHeight = QApplication::screens().at(0)->size().height(); if (fixed_size > iScreenHeight) fixed_size = iScreenHeight; mPopup->setFixedSize(winWidth + 6, fixed_size); } mPopup->adjustSize(); } void UKUITaskGroup::timeout() { if(mTaskGroupEvent == ENTEREVENT) { if(mTimer->isActive()) { mTimer->stop(); } handleSavedEvent(); } else if(mTaskGroupEvent == LEAVEEVENT) { if(mTimer->isActive()) { mTimer->stop(); } setPopupVisible(false); QToolButton::leaveEvent(mEvent); taskgroupStatus = NORMAL; update(); } else { setPopupVisible(false); } } int UKUITaskGroup::calcAverageHeight() { if(plugin()->panel()->isHorizontal()) { return 0; } else { int size = mVisibleHash.size(); int iScreenHeight = QApplication::screens().at(0)->size().height(); int iMarginHeight = (size+1)*3; int iAverageHeight = (iScreenHeight - iMarginHeight)/size;//calculate average width of window return iAverageHeight; } } int UKUITaskGroup::calcAverageWidth() { if(plugin()->panel()->isHorizontal()) { int size = mVisibleHash.size(); int iScreenWidth = QApplication::screens().at(0)->size().width(); int iMarginWidth = (size+1)*3; int iAverageWidth; iAverageWidth = (size == 0 ? size : (iScreenWidth - iMarginWidth)/size);//calculate average width of window return iAverageWidth; } else { return 0; } } void UKUITaskGroup::showAllWindowByList() { int winWidth = 246; int winheight = 46; int iPreviewPosition = 0; int popWindowheight = (winheight) * (mVisibleHash.size()); int screenAvailabelHeight = QApplication::screens().at(0)->size().height() - plugin()->panel()->panelSize(); if(!plugin()->panel()->isHorizontal()) { screenAvailabelHeight = QApplication::screens().at(0)->size().height();//panel is vect } if(mPopup->layout()->count() > 0) { removeSrollWidget(); } mpScrollArea = new QScrollArea(this); mpScrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); mpScrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); //mpScrollArea->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); mpScrollArea->setWidgetResizable(true); mpScrollArea->setFrameStyle(QFrame::NoFrame); mPopup->layout()->addWidget(mpScrollArea); mPopup->setFixedSize(winWidth, popWindowheight < screenAvailabelHeight? popWindowheight : screenAvailabelHeight); mpWidget = new QWidget(this); mpScrollArea->setWidget(mpWidget); setLayOutForPostion(); /*begin catch preview picture*/ for (UKUITaskButtonHash::const_iterator it = mVisibleHash.begin();it != mVisibleHash.end();it++) { UKUITaskWidget *btn = it.value(); btn->clearMask(); btn->setTitleFixedWidth(mpWidget->width() - 25); btn->setParent(mpScrollArea); btn->removeThumbNail(); btn->addThumbNail(); btn->adjustSize(); btn->setFixedHeight(winheight); connect(btn, &UKUITaskWidget::closeSigtoPop, [this] { mPopup->pubcloseWindowDelay(); }); connect(btn, &UKUITaskWidget::closeSigtoGroup, [this] { closeGroup(); }); mpWidget->layout()->addWidget(btn); } /*end*/ plugin()->willShowWindow(mPopup); if(plugin()->panel()->isHorizontal()) { iPreviewPosition = plugin()->panel()->panelSize()/2 - winWidth/2; mPopup->setGeometry(plugin()->panel()->calculatePopupWindowPos(mapToGlobal(QPoint(iPreviewPosition,0)), mPopup->size())); } else { iPreviewPosition = plugin()->panel()->panelSize()/2 - winWidth/2; mPopup->setGeometry(plugin()->panel()->calculatePopupWindowPos(mapToGlobal(QPoint(0,iPreviewPosition)), mPopup->size())); } mpScrollArea->show(); mPopup->show(); // emit popupShown(this); } void UKUITaskGroup::showAllWindowByThumbnail() { if (isWaylandGroup) { int previewPosition = 0; mpWidget = new QWidget(); mpWidget->setAttribute(Qt::WA_TranslucentBackground); for (UKUITaskButtonHash::const_iterator it = mButtonHash.begin();it != mButtonHash.end();it++) { QPixmap thumbnail; UKUITaskWidget *btn = it.value(); thumbnail = QIcon::fromTheme(mIconName).pixmap(THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT - 160); btn->setThumbNail(thumbnail); btn->wl_updateTitle(mCaption); btn->wl_updateIcon(mIconName); btn->setFixedSize(THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT - 160); //mpWidget->layout()->setContentsMargins(0,0,0,0); //mpWidget->layout()->addWidget(btn); } adjustPopWindowSize(THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT - 160); if(plugin()->panel()->isHorizontal())//set preview window position { if(mPopup->size().width()/2 < QCursor::pos().x()) { previewPosition = 0 - mPopup->size().width()/2 + plugin()->panel()->panelSize()/2; } else { previewPosition = 0 -(QCursor::pos().x() + plugin()->panel()->panelSize()/2); } mPopup->setGeometry(plugin()->panel()->calculatePopupWindowPos(mapToGlobal(QPoint(previewPosition,0)), mPopup->size())); } else { if(mPopup->size().height()/2 < QCursor::pos().y()) { previewPosition = 0 - mPopup->size().height()/2 + plugin()->panel()->panelSize()/2; } else { previewPosition = 0 -(QCursor::pos().y() + plugin()->panel()->panelSize()/2); } mPopup->setGeometry(plugin()->panel()->calculatePopupWindowPos(mapToGlobal(QPoint(0,previewPosition)), mPopup->size())); } if(mPopup->isVisible()) { // mPopup- } else { mPopup->show(); } return; } XImage *img = NULL; Display *display = NULL; QPixmap thumbnail; XWindowAttributes attr; int previewPosition = 0; int winWidth = 0; int winHeight = 0; int truewidth = 0; // initVisibleHash(); refreshVisibility(); int iAverageWidth = calcAverageWidth(); int iAverageHeight = calcAverageHeight(); /*begin get the winsize*/ bool isMaxWinSize = isSetMaxWindow(); if(isMaxWinSize) { if(0 == iAverageWidth) { winHeight = PREVIEW_WIDGET_MAX_HEIGHT < iAverageHeight?PREVIEW_WIDGET_MAX_HEIGHT:iAverageHeight; winWidth = winHeight*PREVIEW_WIDGET_MAX_WIDTH/PREVIEW_WIDGET_MAX_HEIGHT; } else { winWidth = PREVIEW_WIDGET_MAX_WIDTH < iAverageWidth?PREVIEW_WIDGET_MAX_WIDTH:iAverageWidth; winHeight = winWidth*PREVIEW_WIDGET_MAX_HEIGHT/PREVIEW_WIDGET_MAX_WIDTH; } } else { if(0 == iAverageWidth) { winHeight = PREVIEW_WIDGET_MIN_HEIGHT < iAverageHeight?PREVIEW_WIDGET_MIN_HEIGHT:iAverageHeight; winWidth = winHeight*PREVIEW_WIDGET_MIN_WIDTH/PREVIEW_WIDGET_MIN_HEIGHT; } else { winWidth = PREVIEW_WIDGET_MIN_WIDTH < iAverageWidth?PREVIEW_WIDGET_MIN_WIDTH:iAverageWidth; winHeight = winWidth*PREVIEW_WIDGET_MIN_HEIGHT/PREVIEW_WIDGET_MIN_WIDTH; } } /*end get the winsize*/ if(mPopup->layout()->count() > 0) { removeWidget(); } mpWidget = new QWidget; mpWidget->setAttribute(Qt::WA_TranslucentBackground); setLayOutForPostion(); /*begin catch preview picture*/ int max_Height = 0; int max_Width = 0; int imgWidth_sum = 0; int changed = 0; int title_width = 0; int v_all = 0; int iScreenWidth = QApplication::screens().at(0)->size().width(); float minimumHeight = THUMBNAIL_HEIGHT; int allwidth = winWidth * mVisibleHash.size(); for (UKUITaskButtonHash::const_iterator it = mVisibleHash.begin();it != mVisibleHash.end();it++) { it.value()->removeThumbNail(); display = XOpenDisplay(nullptr); XGetWindowAttributes(display, it.key(), &attr); max_Height = attr.height > max_Height ? attr.height : max_Height; max_Width = attr.width > max_Width ? attr.width : max_Width; truewidth += attr.width; if(display) XCloseDisplay(display); } for (UKUITaskButtonHash::const_iterator it = mButtonHash.begin();it != mButtonHash.end();it++) { UKUITaskWidget *btn = it.value(); btn->setParent(mPopup); connect(btn, &UKUITaskWidget::closeSigtoPop, [this] { mPopup->pubcloseWindowDelay(); }); connect(btn, &UKUITaskWidget::closeSigtoGroup, [this] { closeGroup(); }); btn->addThumbNail(); display = XOpenDisplay(nullptr); XGetWindowAttributes(display, it.key(), &attr); img = XGetImage(display, it.key(), 0, 0, attr.width, attr.height, 0xffffffff,ZPixmap); float imgWidth = 0; float imgHeight = 0; if (plugin()->panel()->isHorizontal()) { float thmbwidth = (float)attr.width / (float)attr.height; imgWidth = thmbwidth * winHeight; imgHeight = winHeight; if (imgWidth > THUMBNAIL_WIDTH) imgWidth = THUMBNAIL_WIDTH; } else { imgWidth = THUMBNAIL_WIDTH; imgHeight = (float)attr.height / (float)attr.width * THUMBNAIL_WIDTH ; } if (plugin()->panel()->isHorizontal()) { if (mVisibleHash.contains(btn->windowId())) { v_all += (int)imgWidth; imgWidth_sum += (int)imgWidth; } if (mVisibleHash.size() == 1 ) changed = (int)imgWidth; btn->setThumbMaximumSize(MAX_SIZE_OF_Thumb); btn->setThumbScale(true); } else { if (attr.width != max_Width) { float tmp = (float)attr.width / (float)max_Width; imgWidth = imgWidth * tmp; } if ((int)imgHeight > (int)minimumHeight) { imgHeight = minimumHeight; } if (mVisibleHash.contains(btn->windowId())) { v_all += (int)imgHeight; } if (mVisibleHash.size() == 1 ) changed = (int)imgHeight; if ((int)imgWidth < 150) { btn->setThumbFixedSize((int)imgWidth); btn->setThumbScale(false); } else { btn->setThumbMaximumSize(MAX_SIZE_OF_Thumb); btn->setThumbScale(true); } } if(img) { thumbnail = qimageFromXImage(img).scaled((int)imgWidth, (int)imgHeight, Qt::KeepAspectRatio,Qt::SmoothTransformation); if (!parentTaskBar()->getCpuInfoFlg()) thumbnail.save(QString("/tmp/%1.png").arg(it.key())); } else { qDebug()<<"can not catch picture"; QPixmap pxmp; if (pxmp.load(QString("/tmp/%1.png").arg(it.key()))) thumbnail = pxmp.scaled((int)imgWidth, (int)imgHeight, Qt::KeepAspectRatio,Qt::SmoothTransformation); else { thumbnail = QPixmap((int)imgWidth, (int)imgHeight); thumbnail.fill(QColor(0, 0, 0, 127)); } } btn->setThumbNail(thumbnail); btn->updateTitle(); btn->setFixedSize((int)imgWidth, (int)imgHeight); mpWidget->layout()->setContentsMargins(0,0,0,0); mpWidget->layout()->addWidget(btn); if(img) { XDestroyImage(img); } if(display) { XCloseDisplay(display); } } /*end*/ for (UKUITaskButtonHash::const_iterator it = mButtonHash.begin();it != mButtonHash.end();it++) { UKUITaskWidget *btn = it.value(); if (plugin()->panel()->isHorizontal()) { if (imgWidth_sum > iScreenWidth) title_width = (int)(btn->width() * iScreenWidth / imgWidth_sum - 80); else title_width = btn->width() - 75; } else { title_width = winWidth- 70; } btn->setTitleFixedWidth(title_width); } plugin()->willShowWindow(mPopup); mPopup->layout()->addWidget(mpWidget); if (mVisibleHash.size() == 1 && changed != 0) if (plugin()->panel()->isHorizontal()) { adjustPopWindowSize(changed, winHeight); } else { adjustPopWindowSize(winWidth, changed); } else if (mVisibleHash.size() != 1) v_adjustPopWindowSize(winWidth, winHeight, v_all); else adjustPopWindowSize(winWidth, winHeight); if(plugin()->panel()->isHorizontal())//set preview window position { if(mPopup->size().width()/2 < QCursor::pos().x()) { previewPosition = 0 - mPopup->size().width()/2 + plugin()->panel()->panelSize()/2; } else { previewPosition = 0 -(QCursor::pos().x() + plugin()->panel()->panelSize()/2); } mPopup->setGeometry(plugin()->panel()->calculatePopupWindowPos(mapToGlobal(QPoint(previewPosition,0)), mPopup->size())); } else { if(mPopup->size().height()/2 < QCursor::pos().y()) { previewPosition = 0 - mPopup->size().height()/2 + plugin()->panel()->panelSize()/2; } else { previewPosition = 0 -(QCursor::pos().y() + plugin()->panel()->panelSize()/2); } mPopup->setGeometry(plugin()->panel()->calculatePopupWindowPos(mapToGlobal(QPoint(0,previewPosition)), mPopup->size())); } if(mPopup->isVisible()) { // mPopup- } { mPopup->show(); } // emit popupShown(this); } ukui-panel-3.0.6.4/plugin-taskbar-wayland/ukuitaskbar.cpp0000644000175000017500000010230414204636772022000 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2011 Razor team * 2014 LXQt team * Authors: * Alexander Sokoloff * Maciej Płaza * Kuzma Shapran * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include #include #include #include #include #include #include #include #include #include #include #include #include "../panel/common/ukuigridlayout.h" #include "../panel/customstyle.h" #include "ukuitaskbar.h" #include "ukuitaskgroup.h" #include "ukuitaskbaricon.h" using namespace UKUi; /************************************************ ************************************************/ UKUITaskBar::UKUITaskBar(IUKUIPanelPlugin *plugin, QWidget *parent) : QFrame(parent), mSignalMapper(new QSignalMapper(this)), mButtonStyle(Qt::ToolButtonIconOnly), mButtonWidth(400), mButtonHeight(100), mCloseOnMiddleClick(true), mRaiseOnCurrentDesktop(true), mShowOnlyOneDesktopTasks(true), mShowDesktopNum(0), mShowOnlyCurrentScreenTasks(false), mShowOnlyMinimizedTasks(false), mAutoRotate(true), mGroupingEnabled(true), mShowGroupOnHover(true), mIconByClass(false), mCycleOnWheelScroll(true), mPlugin(plugin), mPlaceHolder(new QWidget(this)), mStyle(new LeftAlignedTextStyle()) { taskstatus=NORMAL; setAttribute(Qt::WA_TranslucentBackground);//设置窗口背景透明 setWindowFlags(Qt::FramelessWindowHint); //设置无边框窗口 //setStyle(mStyle); mpTaskBarIcon = new UKUITaskBarIcon; mLayout = new UKUi::GridLayout(this); setLayout(mLayout); mLayout->setMargin(0); mLayout->setStretch(UKUi::GridLayout::StretchHorizontal | UKUi::GridLayout::StretchVertical); realign(); mPlaceHolder->setMinimumSize(1, 1); mPlaceHolder->setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); mPlaceHolder->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding)); mLayout->addWidget(mPlaceHolder); QTimer::singleShot(0,[this] {refreshPlaceholderVisibility();}); // QTimer::singleShot(0, this, SLOT(settingsChanged())); settingsChanged(); // setButtonStyle(Qt::ToolButtonIconOnly); setAcceptDrops(true); mAndroidIconHash=matchAndroidIcon(); const QByteArray id_Theme("org.ukui.style"); if(QGSettings::isSchemaInstalled(id_Theme)){ changeTheme = new QGSettings(id_Theme); } connect(changeTheme, &QGSettings::changed, this, [=] (const QString &key){ if(key=="iconThemeName"){ sleep(1); for(auto it= mKnownWindows.begin(); it != mKnownWindows.end();it++) { UKUITaskGroup *group = it.value(); group->updateIcon(); } } }); connect(mSignalMapper, static_cast(&QSignalMapper::mapped), this, &UKUITaskBar::activateTask); QTimer::singleShot(0, this, &UKUITaskBar::registerShortcuts); connect(KWindowSystem::self(), static_cast(&KWindowSystem::windowChanged) , this, &UKUITaskBar::onWindowChanged); connect(KWindowSystem::self(), &KWindowSystem::windowAdded, this, &UKUITaskBar::onWindowAdded); connect(KWindowSystem::self(), &KWindowSystem::windowRemoved, this, &UKUITaskBar::onWindowRemoved); //龙芯机器的最小化任务窗口的预览窗口的特殊处理 system("cat /proc/cpuinfo >> /tmp/_tmp_cpu_info_cat_"); QFile file("/tmp/_tmp_cpu_info_cat_"); if (!file.open(QIODevice::ReadOnly)) qDebug() << "Read CpuInfo Failed."; while (CpuInfoFlg && !file.atEnd()) { QByteArray line = file.readLine(); QString str(line); if (str.contains("Loongson")) CpuInfoFlg = false; } file.close(); /**/ QDBusConnection::sessionBus().unregisterService("com.ukui.panel.plugins.service"); QDBusConnection::sessionBus().registerService("com.ukui.panel.plugins.service"); QDBusConnection::sessionBus().registerObject("/taskbar/click", this,QDBusConnection :: ExportAllSlots | QDBusConnection :: ExportAllSignals); QDBusConnection::sessionBus().connect(QString(), QString("/"), "com.ukui.panel", "event", this, SLOT(wl_kwinSigHandler(quint32,int, QString, QString))); printf("\ninit finished\n"); //addWindow_wl(QString("application-x-desktop"), QString("ajioajsiof"), 45517); } /************************************************ ************************************************/ UKUITaskBar::~UKUITaskBar() { delete mStyle; if(mpTaskBarIcon) { delete mpTaskBarIcon; mpTaskBarIcon = nullptr; } } /************************************************ ************************************************/ void UKUITaskBar::wl_kwinSigHandler(quint32 wl_winId, int opNo, QString wl_iconName, QString wl_caption) { qDebug()<<"UKUITaskBar::wl_kwinSigHandler"<setActivateState_wl(false); break; case 2: onWindowRemoved(wl_winId); break; case 3: mKnownWindows.find(wl_winId).value()->setActivateState_wl(true); break; case 4: addWindow_wl(wl_iconName, wl_caption, wl_winId); mKnownWindows.find(wl_winId).value()->wl_widgetUpdateTitle(wl_caption); break; } } bool UKUITaskBar::acceptWindow(WId window) const { QFlags ignoreList; ignoreList |= NET::DesktopMask; ignoreList |= NET::DockMask; ignoreList |= NET::SplashMask; ignoreList |= NET::ToolbarMask; ignoreList |= NET::MenuMask; ignoreList |= NET::PopupMenuMask; ignoreList |= NET::NotificationMask; KWindowInfo info(window, NET::WMWindowType | NET::WMState, NET::WM2TransientFor); if (!info.valid()) return false; if (NET::typeMatchesMask(info.windowType(NET::AllTypesMask), ignoreList)) return false; if (info.state() & NET::SkipTaskbar) return false; // WM_TRANSIENT_FOR hint not set - normal window WId transFor = info.transientFor(); if (transFor == 0 || transFor == window || transFor == (WId) QX11Info::appRootWindow()) return true; info = KWindowInfo(transFor, NET::WMWindowType); QFlags normalFlag; normalFlag |= NET::NormalMask; normalFlag |= NET::DialogMask; normalFlag |= NET::UtilityMask; return !NET::typeMatchesMask(info.windowType(NET::AllTypesMask), normalFlag); } bool UKUITaskBar::ignoreSymbolCMP(QString filename,QString groupname) { if (filename.isEmpty()) return false; groupname.replace(" ", ""); groupname.replace("-", "."); groupname.replace(".demo", ""); groupname.replace(".py", ""); groupname.replace("org.", ""); groupname.replace(".qt", ""); filename.replace(" ", ""); filename.replace("-", "."); filename.replace("org.", ""); filename.replace(".desktop", ""); if (groupname.toLower().contains(filename.toLower(), Qt::CaseInsensitive)) return true; if (filename.toLower().contains(groupname.toLower(), Qt::CaseInsensitive)) return true; if (groupname.toLower().contains("kylinweather") && filename.toLower().contains("china.weather")) return true; if (groupname.toLower().contains("srhuijian") && filename.toLower().contains("huijian")) return true; if (groupname.contains("用户手册") && filename.toLower().contains("kylin.user.guid")) return true; if (groupname.toLower().contains("wpsoffice") && filename.toLower().contains("wps.office.prometheus")) return true; if (groupname.toLower().contains("ukuisystemmonitor") && filename.toLower().contains("ukui.system.monitor")) return true; return false; } /************************************************ ************************************************/ void UKUITaskBar::dragEnterEvent(QDragEnterEvent* event) { if (event->mimeData()->hasFormat(UKUITaskGroup::mimeDataFormat())) { event->acceptProposedAction(); buttonMove(nullptr, qobject_cast(event->source()), event->pos()); } else event->ignore(); QWidget::dragEnterEvent(event); } /************************************************ ************************************************/ void UKUITaskBar::dragMoveEvent(QDragMoveEvent * event) { //we don't get any dragMoveEvents if dragEnter wasn't accepted buttonMove(nullptr, qobject_cast(event->source()), event->pos()); QWidget::dragMoveEvent(event); } /************************************************ ************************************************/ void UKUITaskBar::buttonMove(UKUITaskGroup * dst, UKUITaskGroup * src, QPoint const & pos) { int src_index; if (!src || -1 == (src_index = mLayout->indexOf(src))) { qDebug() << "Dropped invalid"; return; } const int size = mLayout->count(); Q_ASSERT(0 < size); //dst is nullptr in case the drop occured on empty space in taskbar int dst_index; if (nullptr == dst) { //moving based on taskbar (not signaled by button) QRect occupied = mLayout->occupiedGeometry(); QRect last_empty_row{occupied}; const QRect last_item_geometry = mLayout->itemAt(size - 1)->geometry(); if (mPlugin->panel()->isHorizontal()) { if (isRightToLeft()) { last_empty_row.setTopRight(last_item_geometry.topLeft()); } else { last_empty_row.setTopLeft(last_item_geometry.topRight()); } } else { if (isRightToLeft()) { last_empty_row.setTopRight(last_item_geometry.topRight()); } else { last_empty_row.setTopLeft(last_item_geometry.topLeft()); } } if (occupied.contains(pos) && !last_empty_row.contains(pos)) return; dst_index = size; } else { //moving based on signal from child button dst_index = mLayout->indexOf(dst); } //moving lower index to higher one => consider as the QList::move => insert(to, takeAt(from)) if (src_index < dst_index) { if (size == dst_index || src_index + 1 != dst_index) { --dst_index; } else { //switching positions of next standing const int tmp_index = src_index; src_index = dst_index; dst_index = tmp_index; } } if (dst_index == src_index || mLayout->animatedMoveInProgress() ) return; mLayout->moveItem(src_index, dst_index, true); } /************************************************ ************************************************/ void UKUITaskBar::groupBecomeEmptySlot() { //group now contains no buttons - clean up in hash and delete the group UKUITaskGroup * const group = qobject_cast(sender()); Q_ASSERT(group); for (auto i = mKnownWindows.begin(); mKnownWindows.end() != i; ) { if (group == *i) i = mKnownWindows.erase(i); else ++i; } mLayout->removeWidget(group); group->deleteLater(); } QString UKUITaskBar::captionExchange(QString str) { QString temp_group_id=str; QStringList strList = temp_group_id.split(" "); QString group_id = strList[0]; QStringList video_list; if(mAndroidIconHash.keys().contains(temp_group_id)){ group_id=mAndroidIconHash.value(temp_group_id); }else{ video_list<<"影音"<<"Video"; if(video_list.contains(group_id)) group_id ="kylin-video"; else group_id="application-x-desktop"; } return group_id; } void UKUITaskBar::addWindow_wl(QString iconName, QString caption, WId window) { // If grouping disabled group behaves like regular button // QString temp_group_id=caption; // QStringList strList = temp_group_id.split(" "); const QString group_id = captionExchange(caption); if(QIcon::fromTheme(group_id).isNull()){ iconName=QDir::homePath()+"/.local/share/icons/"+group_id+".png"; }else{ iconName=group_id; } UKUITaskGroup *group = nullptr; auto i_group = mKnownWindows.find(window); if (mKnownWindows.end() != i_group) { if ((*i_group)->groupName() == group_id) group = *i_group; else (*i_group)->onWindowRemoved(window); } if (!group && mGroupingEnabled && group_id.compare("kylin-video")) { for (auto i = mKnownWindows.cbegin(), i_e = mKnownWindows.cend(); i != i_e; ++i) { if ((*i)->groupName() == group_id) { group = *i; break; } } } if (!group) { group = new UKUITaskGroup(iconName, caption, window, this); mPlaceHolder->hide(); connect(group, SIGNAL(groupBecomeEmpty(QString)), this, SLOT(groupBecomeEmptySlot())); connect(group, SIGNAL(visibilityChanged(bool)), this, SLOT(refreshPlaceholderVisibility())); connect(group, &UKUITaskGroup::popupShown, this, &UKUITaskBar::popupShown); connect(group, &UKUITaskButton::dragging, this, [this] (QObject * dragSource, QPoint const & pos) { buttonMove(qobject_cast(sender()), qobject_cast(dragSource), pos); }); //wayland临时图标适配主题代码处理 /*********************************************/ if(QIcon::fromTheme(group_id).hasThemeIcon(group_id)){ group->setIcon(QIcon::fromTheme(group_id)); }else{ group->setIcon(QIcon::fromTheme(QDir::homePath()+"/.local/share/icons/"+group_id+".png")); } connect(changeTheme, &QGSettings::changed, this, [=] (const QString &key){ if(key=="iconThemeName"){ sleep(1); if(QIcon::fromTheme(group_id).hasThemeIcon(group_id)){ group->setIcon(QIcon::fromTheme(group_id)); }else{ group->setIcon(QIcon::fromTheme(QDir::homePath()+"/.local/share/icons/"+group_id+".png")); } } }); /*********************************************/ // group->setFixedSize(panel()->panelSize(),panel()->panelSize()); //group->setFixedSize(40,40); mLayout->addWidget(group) ; group->wl_widgetUpdateTitle(caption); group->setStyle(new CustomStyle("taskbutton")); group->setToolButtonsStyle(mButtonStyle); } mKnownWindows[window] = group; group->wl_addWindow(window); } QHash UKUITaskBar::matchAndroidIcon() { QHash hash; printf("*************\n"); QFile file("/usr/share/ukui/ukui-panel/plugin-taskbar/name-icon.match"); if(!file.open(QIODevice::ReadOnly)) qDebug()<<"Read FIle failed"; while (!file.atEnd()){ QByteArray line= file.readLine(); QString str=file.readLine(); str.section('picture',1,1).trimmed().toStdString(); str.simplified(); QString str_name = str.section(QRegExp("[;]"),0,0); str_name = str_name.simplified(); str_name = str_name.remove("name="); QString str_icon = str.section(QRegExp("[;]"),1,1); str_icon = str_icon.simplified(); str_icon = str_icon.remove("icon="); hash.insert(str_name,str_icon); } return hash; } /************************************************ ************************************************/ void UKUITaskBar::addWindow(WId window) { // If grouping disabled group behaves like regular button const QString group_id = mGroupingEnabled ? KWindowInfo(window, 0, NET::WM2WindowClass).windowClassClass() : QString("%1").arg(window); //针对ukui-menu和ukui-sidebar做的特殊处理,及时窗口是普通窗口,也不在任务栏显示 if(group_id.compare("ukui-menu")==0 || group_id.compare("ukui-sidebar")==0 || group_id.compare("ukui-search")==0) { return; } UKUITaskGroup *group = nullptr; auto i_group = mKnownWindows.find(window); if (mKnownWindows.end() != i_group) { if ((*i_group)->groupName() == group_id) group = *i_group; else (*i_group)->onWindowRemoved(window); } /*check if window belongs to some existing group * 安卓兼容应用的组名为kydroid-display-window * 需要将安卓兼容目录的分组特性关闭 */ QStringList andriod_window_list; andriod_window_list<<"kydroid-display-window"<<"kylin-kmre-window"; if (!group && mGroupingEnabled && !andriod_window_list.contains(group_id)) { for (auto i = mKnownWindows.cbegin(), i_e = mKnownWindows.cend(); i != i_e; ++i) { if ((*i)->groupName() == group_id) { group = *i; break; } } } if (!group) { group = new UKUITaskGroup(group_id, window, this); connect(group, SIGNAL(groupBecomeEmpty(QString)), this, SLOT(groupBecomeEmptySlot())); connect(group, SIGNAL(visibilityChanged(bool)), this, SLOT(refreshPlaceholderVisibility())); connect(group, &UKUITaskGroup::popupShown, this, &UKUITaskBar::popupShown); connect(group, &UKUITaskButton::dragging, this, [this] (QObject * dragSource, QPoint const & pos) { buttonMove(qobject_cast(sender()), qobject_cast(dragSource), pos); }); //group->setFixedSize(panel()->panelSize(),panel()->panelSize()); mLayout->addWidget(group); group->setToolButtonsStyle(mButtonStyle); } mKnownWindows[window] = group; group->addWindow(window); group->groupName(); } /************************************************ ************************************************/ auto UKUITaskBar::removeWindow(windowMap_t::iterator pos) -> windowMap_t::iterator { WId const window = pos.key(); UKUITaskGroup * const group = *pos; auto ret = mKnownWindows.erase(pos); group->onWindowRemoved(window); return ret; } /************************************************ ************************************************/ void UKUITaskBar::refreshTaskList() { QList new_list; // Just add new windows to groups, deleting is up to the groups const auto wnds = KWindowSystem::stackingOrder(); for (auto const wnd: wnds) { if (acceptWindow(wnd)) { new_list << wnd; addWindow(wnd); } } //emulate windowRemoved if known window not reported by KWindowSystem for (auto i = mKnownWindows.begin(), i_e = mKnownWindows.end(); i != i_e; ) { if (0 > new_list.indexOf(i.key())) { i = removeWindow(i); } else ++i; } refreshPlaceholderVisibility(); } /************************************************ ************************************************/ void UKUITaskBar::onWindowChanged(WId window, NET::Properties prop, NET::Properties2 prop2) { auto i = mKnownWindows.find(window); if (mKnownWindows.end() != i) { if (!(*i)->onWindowChanged(window, prop, prop2) && acceptWindow(window)) { // window is removed from a group because of class change, so we should add it again addWindow(window); } } } void UKUITaskBar::onWindowAdded(WId window) { auto const pos = mKnownWindows.find(window); if (mKnownWindows.end() == pos && acceptWindow(window)) addWindow(window); } /************************************************ ************************************************/ void UKUITaskBar::onWindowRemoved(WId window) { auto const pos = mKnownWindows.find(window); if (mKnownWindows.end() != pos) { removeWindow(pos); } } /************************************************ ************************************************/ void UKUITaskBar::refreshButtonRotation() { bool autoRotate = mAutoRotate && (mButtonStyle != Qt::ToolButtonIconOnly); IUKUIPanel::Position panelPosition = mPlugin->panel()->position(); // emit buttonRotationRefreshed(autoRotate, panelPosition); } /************************************************ ************************************************/ void UKUITaskBar::refreshPlaceholderVisibility() { // if no visible group button show placeholder widget bool haveVisibleWindow = false; for (auto i = mKnownWindows.cbegin(), i_e = mKnownWindows.cend(); i_e != i; ++i) { if ((*i)->isVisible()) { haveVisibleWindow = true; break; } } mPlaceHolder->setVisible(!haveVisibleWindow); if (haveVisibleWindow) mPlaceHolder->setFixedSize(0, 0); else { mPlaceHolder->setMinimumSize(1, 1); mPlaceHolder->setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); } } /************************************************ ************************************************/ void UKUITaskBar::setButtonStyle(Qt::ToolButtonStyle buttonStyle) { emit buttonStyleRefreshed(mButtonStyle); } void UKUITaskBar::settingsChanged() { bool groupingEnabledOld = mGroupingEnabled; bool showOnlyOneDesktopTasksOld = mShowOnlyOneDesktopTasks; const int showDesktopNumOld = mShowDesktopNum; bool showOnlyCurrentScreenTasksOld = mShowOnlyCurrentScreenTasks; bool showOnlyMinimizedTasksOld = mShowOnlyMinimizedTasks; const bool iconByClassOld = mIconByClass; mButtonWidth = mPlugin->settings()->value("buttonWidth", 400).toInt(); mButtonHeight = mPlugin->settings()->value("buttonHeight", 100).toInt(); QString s = mPlugin->settings()->value("buttonStyle").toString().toUpper(); if (s == "ICON") setButtonStyle(Qt::ToolButtonIconOnly); else if (s == "TEXT") setButtonStyle(Qt::ToolButtonTextOnly); else setButtonStyle(Qt::ToolButtonIconOnly); mShowOnlyOneDesktopTasks = mPlugin->settings()->value("showOnlyOneDesktopTasks", mShowOnlyOneDesktopTasks).toBool(); mShowDesktopNum = mPlugin->settings()->value("showDesktopNum", mShowDesktopNum).toInt(); mShowOnlyCurrentScreenTasks = mPlugin->settings()->value("showOnlyCurrentScreenTasks", mShowOnlyCurrentScreenTasks).toBool(); mShowOnlyMinimizedTasks = mPlugin->settings()->value("showOnlyMinimizedTasks", mShowOnlyMinimizedTasks).toBool(); mAutoRotate = mPlugin->settings()->value("autoRotate", true).toBool(); mCloseOnMiddleClick = mPlugin->settings()->value("closeOnMiddleClick", true).toBool(); mRaiseOnCurrentDesktop = mPlugin->settings()->value("raiseOnCurrentDesktop", false).toBool(); mGroupingEnabled = mPlugin->settings()->value("groupingEnabled",true).toBool(); mShowGroupOnHover = mPlugin->settings()->value("showGroupOnHover",true).toBool(); mIconByClass = mPlugin->settings()->value("iconByClass", false).toBool(); mCycleOnWheelScroll = mPlugin->settings()->value("cycleOnWheelScroll", true).toBool(); // Delete all groups if grouping feature toggled and start over if (groupingEnabledOld != mGroupingEnabled) { for (int i = mLayout->count() - 1; 0 <= i; --i) { UKUITaskGroup * group = qobject_cast(mLayout->itemAt(i)->widget()); if (nullptr != group) { mLayout->takeAt(i); group->deleteLater(); } } mKnownWindows.clear(); } if (showOnlyOneDesktopTasksOld != mShowOnlyOneDesktopTasks || (mShowOnlyOneDesktopTasks && showDesktopNumOld != mShowDesktopNum) || showOnlyCurrentScreenTasksOld != mShowOnlyCurrentScreenTasks || showOnlyMinimizedTasksOld != mShowOnlyMinimizedTasks ) emit showOnlySettingChanged(); if (iconByClassOld != mIconByClass) emit iconByClassChanged(); refreshTaskList(); } void UKUITaskBar::setShowGroupOnHover(bool bFlag) { mShowGroupOnHover = bFlag; } void UKUITaskBar::realign() { mLayout->setEnabled(false); refreshButtonRotation(); IUKUIPanel *panel = mPlugin->panel(); //set taskbar width by panel QSize maxSize = QSize(mPlugin->panel()->panelSize(), mPlugin->panel()->panelSize()); QSize minSize = QSize(mPlugin->panel()->iconSize()/2, mPlugin->panel()->iconSize()/2); int iconsize = panel->iconSize(); int panelsize = panel->panelSize(); bool rotated = false; if (panel->isHorizontal()) { mLayout->setRowCount(panel->lineCount()); mLayout->setColumnCount(0); } else { mLayout->setRowCount(0); if (mButtonStyle == Qt::ToolButtonIconOnly) { // Vertical + Icons mLayout->setColumnCount(panel->lineCount()); } else { rotated = mAutoRotate && (panel->position() == IUKUIPanel::PositionLeft || panel->position() == IUKUIPanel::PositionRight); // Vertical + Text if (rotated) { maxSize.rwidth() = mButtonHeight; maxSize.rheight() = mButtonWidth; mLayout->setColumnCount(panel->lineCount()); } else { mLayout->setColumnCount(1); } } } for(auto it= mKnownWindows.begin(); it != mKnownWindows.end();it++) { UKUITaskGroup *group = it.value(); //group->setFixedSize(panelsize, panelsize); group->setIconSize(QSize(iconsize,iconsize)); // group->updateIcon(); } mLayout->setCellMinimumSize(minSize); mLayout->setCellMaximumSize(maxSize); mLayout->setDirection(rotated ? UKUi::GridLayout::TopToBottom : UKUi::GridLayout::LeftToRight); mLayout->setEnabled(true); //our placement on screen could have been changed emit showOnlySettingChanged(); emit refreshIconGeometry(); } /************************************************ ************************************************/ void UKUITaskBar::wheelEvent(QWheelEvent* event) { #if 0 if (!mCycleOnWheelScroll) return QFrame::wheelEvent(event); static int threshold = 0; threshold += abs(event->delta()); if (threshold < 300) return QFrame::wheelEvent(event); else threshold = 0; int delta = event->delta() < 0 ? 1 : -1; // create temporary list of visible groups in the same order like on the layout QList list; UKUITaskGroup *group = NULL; for (int i = 0; i < mLayout->count(); i++) { QWidget * o = mLayout->itemAt(i)->widget(); UKUITaskGroup * g = qobject_cast(o); if (!g) continue; if (g->isVisible()) list.append(g); if (g->isChecked()) group = g; } if (list.isEmpty()) return QFrame::wheelEvent(event); if (!group) group = list.at(0); UKUITaskButton *button = NULL; // switching between groups from temporary list in modulo addressing while (!button)conSize() { button = group->getNextPrevChildButton(delta == 1, !(list.count() - 1)); if (button) button->raiseApplication(); int idx = (list.indexOf(group) + delta + list.count()) % list.count(); group = list.at(idx); } QFrame::wheelEvent(event); #endif } /************************************************ ************************************************/ void UKUITaskBar::resizeEvent(QResizeEvent* event) { emit refreshIconGeometry(); return QWidget::resizeEvent(event); } /************************************************ ************************************************/ void UKUITaskBar::changeEvent(QEvent* event) { // if current style is changed, reset the base style of the proxy style // so we can apply the new style correctly to task buttons. if(event->type() == QEvent::StyleChange) mStyle->setBaseStyle(NULL); QFrame::changeEvent(event); } /************************************************ ************************************************/ void UKUITaskBar::registerShortcuts() { // Register shortcuts to switch to the task // mPlaceHolder is always at position 0 // tasks are at positions 1..10 // GlobalKeyShortcut::Action * gshortcut; // QString path; // QString description; // for (int i = 1; i <= 10; ++i) // { // path = QString("/panel/%1/task_%2").arg(mPlugin->settings()->group()).arg(i); // description = tr("Activate task %1").arg(i); // gshortcut = GlobalKeyShortcut::Client::instance()->addAction(QStringLiteral(), path, description, this); // if (nullptr != gshortcut) // { // mKeys << gshortcut; // connect(gshortcut, &GlobalKeyShortcut::Action::registrationFinished, this, &UKUITaskBar::shortcutRegistered); // connect(gshortcut, &GlobalKeyShortcut::Action::activated, mSignalMapper, static_cast(&QSignalMapper::map)); // mSignalMapper->setMapping(gshortcut, i); // } // } } void UKUITaskBar::shortcutRegistered() { // GlobalKeyShortcut::Action * const shortcut = qobject_cast(sender()); // disconnect(shortcut, &GlobalKeyShortcut::Action::registrationFinished, this, &UKUITaskBar::shortcutRegistered); // const int i = mKeys.indexOf(shortcut); // Q_ASSERT(-1 != i); // if (shortcut->shortcut().isEmpty()) // { // // Shortcuts come in order they were registered // // starting from index 0 // const int key = (i + 1) % 10; // shortcut->changeShortcut(QStringLiteral("Meta+%1").arg(key)); // } } void UKUITaskBar::activateTask(int pos) { for (int i = 1; i < mLayout->count(); ++i) { QWidget * o = mLayout->itemAt(i)->widget(); UKUITaskGroup * g = qobject_cast(o); if (g && g->isVisible()) { pos--; if (pos == 0) { g->raiseApplication(); break; } } } } void UKUITaskBar::enterEvent(QEvent *) { taskstatus=HOVER; update(); } void UKUITaskBar::leaveEvent(QEvent *) { taskstatus=NORMAL; update(); } void UKUITaskBar::paintEvent(QPaintEvent *) { QStyleOption opt; opt.initFrom(this); QPainter p(this); switch(taskstatus) { case NORMAL: { // p.setBrush(QBrush(QColor(0xFF,0xFF,0xFF,0x19))); p.setPen(Qt::NoPen); break; } case HOVER: { // p.setBrush(QBrush(QColor(0xFF,0xFF,0xFF,0x19))); p.setPen(Qt::NoPen); break; } case PRESS: { // p.setBrush(QBrush(QColor(0x13,0x14,0x14,0xb2))); p.setPen(Qt::NoPen); break; } } p.setRenderHint(QPainter::Antialiasing); p.drawRoundedRect(opt.rect,6,6); style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); } void UKUITaskBar::mousePressEvent(QMouseEvent *) { /*创建QT的DBus信号*/ QDBusMessage message =QDBusMessage::createSignal("/taskbar/click", "com.ukui.panel.plugins.taskbar", "sendToUkuiDEApp"); /* * 发射信号,此处不给信号赋值  message << QString("clicked");的原因是 * 侧边栏和开始菜单仅需要点击信号 * 若后期有特殊的设计需求,例如对鼠标左键,右键,滚轮 进行不同的处理就需要给信号赋值 * tr: * Transmit the signal, the signal is not assigned here The reason is * The sidebar and start menu only need to click the signal * If there are special design requirements in the later stage, * such as different processing for the left mouse button, right mouse button, and scroll wheel, * the signal needs to be assigned and processed * * 需要此点击信号的应用需要做如下绑定 * QDBusConnection::sessionBus().connect(QString(), QString("/taskbar/click"), "com.ukui.panel.plugins.taskbar", "sendToUkuiDEApp", this, SLOT(client_get(void))); * 在槽函数client_get(void) 中处理接受到的点击信号 * tr: * Applications that require this click signal need to do the following binding * Process the received click signal in the slot function client_get (void) * NOTE:https://blog.csdn.net/czhzasui/article/details/81071383    */ QDBusConnection::sessionBus().send(message); } ukui-panel-3.0.6.4/plugin-taskbar-wayland/ukuitaskclosebutton.cpp0000644000175000017500000000401314204636772023573 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include "ukuitaskclosebutton.h" #include "../panel/customstyle.h" #include "../panel/highlight-effect.h" UKUITaskCloseButton::UKUITaskCloseButton(const WId window, QWidget *parent): QToolButton(parent), mWindow(window) { this->setStyle(new CustomStyle("closebutton")); this->setIcon(QIcon(HighLightEffect::drawSymbolicColoredPixmap(QPixmap::fromImage(QIcon::fromTheme("window-close-symbolic").pixmap(24,24).toImage())))); this->setIconSize(QSize(9,9)); //connect(parent, &UKUITaskBar::buttonRotationRefreshed, this, &UKUITaskGroup::setAutoRotation); } /************************************************ ************************************************/ void UKUITaskCloseButton::mousePressEvent(QMouseEvent* event) { // const Qt::MouseButton b = event->button(); // if (Qt::LeftButton == b) // mDragStartPosition = event->pos(); // else if (Qt::MidButton == b && parentTaskBar()->closeOnMiddleClick()) // closeApplication(); QToolButton::mousePressEvent(event); } /************************************************ ************************************************/ void UKUITaskCloseButton::mouseReleaseEvent(QMouseEvent* event) { if (event->button()== Qt::LeftButton) { emit sigClicked(); } QToolButton::mouseReleaseEvent(event); } ukui-panel-3.0.6.4/plugin-taskbar-wayland/ukuitaskbutton.cpp0000644000175000017500000006367414204636772022567 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2011 Razor team * 2014 LXQt team * Authors: * Alexander Sokoloff * Kuzma Shapran * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #include "ukuitaskbutton.h" #include "ukuitaskgroup.h" #include "ukuitaskbar.h" //#include #include "../panel/common/ukuisettings.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ukuitaskgroup.h" #include "ukuitaskbar.h" #include "../panel/customstyle.h" #include "ukuitaskbaricon.h" #include // Necessary for closeApplication() #include #include #define PANEL_SETTINGS "org.ukui.panel.settings" #define PANEL_SIZE_KEY "panelsize" #define ICON_SIZE_KEY "iconsize" #define PANEL_POSITION_KEY "panelposition" bool UKUITaskButton::sDraggging = false; /************************************************ ************************************************/ void LeftAlignedTextStyle::drawItemText(QPainter * painter, const QRect & rect, int flags , const QPalette & pal, bool enabled, const QString & text , QPalette::ColorRole textRole) const { QString txt = QFontMetrics(painter->font()).elidedText(text, Qt::ElideRight, rect.width()); return QProxyStyle::drawItemText(painter, rect, (flags & ~Qt::AlignHCenter) | Qt::AlignLeft, pal, enabled, txt, textRole); } /************************************************ ************************************************/ UKUITaskButton::UKUITaskButton(QString appName,const WId window, UKUITaskBar * taskbar, QWidget *parent) : QToolButton(parent), mWindow(window), mAppName(appName), mUrgencyHint(false), mOrigin(Qt::TopLeftCorner), mDrawPixmap(false), mParentTaskBar(taskbar), mPlugin(mParentTaskBar->plugin()), mDNDTimer(new QTimer(this)) { Q_ASSERT(taskbar); taskbuttonstatus=NORMAL; setCheckable(true); setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); setMinimumWidth(1); setMinimumHeight(1); setToolButtonStyle(Qt::ToolButtonTextBesideIcon); setAcceptDrops(true); updateText(); updateIcon(); mDNDTimer->setSingleShot(true); mDNDTimer->setInterval(700); connect(mDNDTimer, SIGNAL(timeout()), this, SLOT(activateWithDraggable())); connect(UKUi::Settings::globalSettings(), SIGNAL(iconThemeChanged()), this, SLOT(updateIcon())); connect(mParentTaskBar, &UKUITaskBar::iconByClassChanged, this, &UKUITaskButton::updateIcon); const QByteArray id(PANEL_SETTINGS); gsettings = new QGSettings(id); connect(gsettings, &QGSettings::changed, this, [=] (const QString &key){ if (key == PANEL_SIZE_KEY) { updateIcon(); } }); QStringList windowList; qDebug()<<"Window Name"<windowId(), 0, NET::WM2WindowClass).windowClassClass(); windowList<<"kylin-kmre-window"<<"kydroid-display-window"; if(windowList.contains(KWindowInfo(this->windowId(), 0, NET::WM2WindowClass).windowClassClass())){ connect(KWindowSystem::self(), static_cast(&KWindowSystem::windowChanged) , this, &UKUITaskButton::updateIcon); } } UKUITaskButton::UKUITaskButton(QString iconName,QString caption, const WId window, UKUITaskBar * taskbar, QWidget *parent) : QToolButton(parent), mIconName(iconName), mCaption(caption), mWindow(window), mParentTaskBar(taskbar), mPlugin(mParentTaskBar->plugin()) { setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); isWinActivate = true; mIcon = QIcon::fromTheme("application-x-desktop"); } /************************************************ ************************************************/ UKUITaskButton::~UKUITaskButton() { } /************************************************ ************************************************/ void UKUITaskButton::updateText() { KWindowInfo info(mWindow, NET::WMVisibleName | NET::WMName); QString title = info.visibleName().isEmpty() ? info.name() : info.visibleName(); setText(title.replace("&", "&&")); setToolTip(title); } /* int devicePixels = mPlugin->panel()->iconSize() * devicePixelRatioF()是由ico =KWindowSystem:ico(mwindow)更改的 * 目的是为了能够显示正确的application-x-desktop的图标的大小 * */ void UKUITaskButton::setLeaderWindow(WId leaderWindow) { mWindow = leaderWindow; updateIcon(); } void UKUITaskButton::updateIcon() { if (mAppName == QString("emo-system-ShellMethods") || mAppName == QString("Qq")) sleep(1); QIcon ico; int mIconSize=mPlugin->panel()->iconSize(); if (mParentTaskBar->isIconByClass()) { ico = QIcon::fromTheme(QString::fromUtf8(KWindowInfo{mWindow, 0, NET::WM2WindowClass}.windowClassClass()).toLower()); } if(ico.isNull()) { ico = QIcon::fromTheme(mParentTaskBar->fetchIcon()->getIconName(mAppName.replace(" ","").toLower())); } if (ico.isNull()) { #if QT_VERSION >= 0x050600 int devicePixels = mIconSize * devicePixelRatioF(); #else int devicePixels = mIconSize * devicePixelRatio(); #endif ico = KWindowSystem::icon(mWindow, devicePixels, devicePixels); } if (mIcon.isNull()) { mIcon = QIcon::fromTheme("application-x-desktop"); } if (ico.isNull()) { ico = mIcon; } setIcon(ico); setIconSize(QSize(mIconSize,mIconSize)); } void UKUITaskButton::setGroupIcon(QIcon ico) { mIcon = ico; } /************************************************ ************************************************/ void UKUITaskButton::refreshIconGeometry(QRect const & geom) { NETWinInfo info(QX11Info::connection(), windowId(), (WId) QX11Info::appRootWindow(), NET::WMIconGeometry, 0); NETRect const curr = info.iconGeometry(); if (curr.pos.x != geom.x() || curr.pos.y != geom.y() || curr.size.width != geom.width() || curr.size.height != geom.height()) { NETRect nrect; nrect.pos.x = geom.x(); nrect.pos.y = geom.y(); nrect.size.height = geom.height(); nrect.size.width = geom.width(); info.setIconGeometry(nrect); } } /************************************************ ************************************************/ void UKUITaskButton::dragEnterEvent(QDragEnterEvent *event) { // It must be here otherwise dragLeaveEvent and dragMoveEvent won't be called // on the other hand drop and dragmove events of parent widget won't be called event->acceptProposedAction(); if (event->mimeData()->hasFormat(mimeDataFormat())) { emit dragging(event->source(), event->pos()); setAttribute(Qt::WA_UnderMouse, false); } else { mDNDTimer->start(); } QToolButton::dragEnterEvent(event); } void UKUITaskButton::dragMoveEvent(QDragMoveEvent * event) { if (event->mimeData()->hasFormat(mimeDataFormat())) { emit dragging(event->source(), event->pos()); setAttribute(Qt::WA_UnderMouse, false); } } void UKUITaskButton::dragLeaveEvent(QDragLeaveEvent *event) { mDNDTimer->stop(); QToolButton::dragLeaveEvent(event); } void UKUITaskButton::dropEvent(QDropEvent *event) { mDNDTimer->stop(); if (event->mimeData()->hasFormat(mimeDataFormat())) { emit dropped(event->source(), event->pos()); setAttribute(Qt::WA_UnderMouse, false); } QToolButton::dropEvent(event); } /************************************************ ************************************************/ void UKUITaskButton::mousePressEvent(QMouseEvent* event) { const Qt::MouseButton b = event->button(); if (Qt::LeftButton == b) mDragStartPosition = event->pos(); else if (Qt::MidButton == b && parentTaskBar()->closeOnMiddleClick()) closeApplication(); QToolButton::mousePressEvent(event); } /************************************************ ************************************************/ void UKUITaskButton::mouseReleaseEvent(QMouseEvent* event) { // if (event->button() == Qt::LeftButton) // { // if (isChecked()) // minimizeApplication(); // else // { // raiseApplication(); // } // } QToolButton::mouseReleaseEvent(event); } /************************************************ ************************************************/ QMimeData * UKUITaskButton::mimeData() { QMimeData *mimedata = new QMimeData; QByteArray ba; QDataStream stream(&ba,QIODevice::WriteOnly); stream << (qlonglong)(mWindow); mimedata->setData(mimeDataFormat(), ba); return mimedata; } /************************************************ ************************************************/ void UKUITaskButton::mouseMoveEvent(QMouseEvent* event) { if (!(event->buttons() & Qt::LeftButton)) return; if ((event->pos() - mDragStartPosition).manhattanLength() < QApplication::startDragDistance()) return; QDrag *drag = new QDrag(this); drag->setMimeData(mimeData()); QIcon ico = icon(); QPixmap img = ico.pixmap(ico.actualSize({32, 32})); drag->setPixmap(img); switch (parentTaskBar()->panel()->position()) { case IUKUIPanel::PositionLeft: case IUKUIPanel::PositionTop: drag->setHotSpot({0, 0}); break; case IUKUIPanel::PositionRight: case IUKUIPanel::PositionBottom: drag->setHotSpot(img.rect().bottomRight()); break; } sDraggging = true; drag->exec(); // if button is dropped out of panel (e.g. on desktop) // it is not deleted automatically by Qt drag->deleteLater(); sDraggging = false; QAbstractButton::mouseMoveEvent(event); } /************************************************ ************************************************/ bool UKUITaskButton::isApplicationHidden() const { KWindowInfo info(mWindow, NET::WMState); return (info.state() & NET::Hidden); } /************************************************ ************************************************/ bool UKUITaskButton::isApplicationActive() const { return KWindowSystem::activeWindow() == mWindow; } /************************************************ ************************************************/ void UKUITaskButton::activateWithDraggable() { // raise app in any time when there is a drag // in progress to allow drop it into an app raiseApplication(); KWindowSystem::forceActiveWindow(mWindow); } /************************************************ ************************************************/ void UKUITaskButton::raiseApplication() { KWindowInfo info(mWindow, NET::WMDesktop | NET::WMState | NET::XAWMState); if (parentTaskBar()->raiseOnCurrentDesktop() && info.isMinimized()) { KWindowSystem::setOnDesktop(mWindow, KWindowSystem::currentDesktop()); } else { int winDesktop = info.desktop(); if (KWindowSystem::currentDesktop() != winDesktop) KWindowSystem::setCurrentDesktop(winDesktop); } KWindowSystem::activateWindow(mWindow); setUrgencyHint(false); } /************************************************ ************************************************/ void UKUITaskButton::minimizeApplication() { KWindowSystem::minimizeWindow(mWindow); } /************************************************ ************************************************/ void UKUITaskButton::maximizeApplication() { QAction* act = qobject_cast(sender()); if (!act) return; int state = act->data().toInt(); switch (state) { case NET::MaxHoriz: KWindowSystem::setState(mWindow, NET::MaxHoriz); break; case NET::MaxVert: KWindowSystem::setState(mWindow, NET::MaxVert); break; default: KWindowSystem::setState(mWindow, NET::Max); break; } if (!isApplicationActive()) raiseApplication(); } /************************************************ ************************************************/ void UKUITaskButton::deMaximizeApplication() { KWindowSystem::clearState(mWindow, NET::Max); if (!isApplicationActive()) raiseApplication(); } /************************************************ ************************************************/ void UKUITaskButton::shadeApplication() { KWindowSystem::setState(mWindow, NET::Shaded); } /************************************************ ************************************************/ void UKUITaskButton::unShadeApplication() { KWindowSystem::clearState(mWindow, NET::Shaded); } /************************************************ ************************************************/ void UKUITaskButton::closeApplication() { // FIXME: Why there is no such thing in KWindowSystem?? NETRootInfo(QX11Info::connection(), NET::CloseWindow).closeWindowRequest(mWindow); } /************************************************ ************************************************/ void UKUITaskButton::setApplicationLayer() { QAction* act = qobject_cast(sender()); if (!act) return; int layer = act->data().toInt(); switch(layer) { case NET::KeepAbove: KWindowSystem::clearState(mWindow, NET::KeepBelow); KWindowSystem::setState(mWindow, NET::KeepAbove); break; case NET::KeepBelow: KWindowSystem::clearState(mWindow, NET::KeepAbove); KWindowSystem::setState(mWindow, NET::KeepBelow); break; default: KWindowSystem::clearState(mWindow, NET::KeepBelow); KWindowSystem::clearState(mWindow, NET::KeepAbove); break; } } /************************************************ ************************************************/ void UKUITaskButton::moveApplicationToDesktop() { QAction* act = qobject_cast(sender()); if (!act) return; bool ok; int desk = act->data().toInt(&ok); if (!ok) return; KWindowSystem::setOnDesktop(mWindow, desk); } /************************************************ ************************************************/ void UKUITaskButton::moveApplication() { KWindowInfo info(mWindow, NET::WMDesktop); if (!info.isOnCurrentDesktop()) KWindowSystem::setCurrentDesktop(info.desktop()); if (isMinimized()) KWindowSystem::unminimizeWindow(mWindow); KWindowSystem::forceActiveWindow(mWindow); const QRect& g = KWindowInfo(mWindow, NET::WMGeometry).geometry(); int X = g.center().x(); int Y = g.center().y(); QCursor::setPos(X, Y); NETRootInfo(QX11Info::connection(), NET::WMMoveResize).moveResizeRequest(mWindow, X, Y, NET::Move); } /************************************************ ************************************************/ void UKUITaskButton::resizeApplication() { KWindowInfo info(mWindow, NET::WMDesktop); if (!info.isOnCurrentDesktop()) KWindowSystem::setCurrentDesktop(info.desktop()); if (isMinimized()) KWindowSystem::unminimizeWindow(mWindow); KWindowSystem::forceActiveWindow(mWindow); const QRect& g = KWindowInfo(mWindow, NET::WMGeometry).geometry(); int X = g.bottomRight().x(); int Y = g.bottomRight().y(); QCursor::setPos(X, Y); NETRootInfo(QX11Info::connection(), NET::WMMoveResize).moveResizeRequest(mWindow, X, Y, NET::BottomRight); } /************************************************ ************************************************/ void UKUITaskButton::contextMenuEvent(QContextMenuEvent* event) { if (event->modifiers().testFlag(Qt::ControlModifier)) { event->ignore(); return; } KWindowInfo info(mWindow, 0, NET::WM2AllowedActions); unsigned long state = KWindowInfo(mWindow, NET::WMState).state(); QMenu * menu = new QMenu(tr("Application")); menu->setAttribute(Qt::WA_DeleteOnClose); QAction* a; /* KDE menu ******* + To &Desktop > + &All Desktops + --- + &1 Desktop 1 + &2 Desktop 2 + &To Current Desktop &Move Re&size + Mi&nimize + Ma&ximize + &Shade Ad&vanced > Keep &Above Others Keep &Below Others Fill screen &Layer > Always on &top &Normal Always on &bottom --- + &Close */ /********** Desktop menu **********/ int deskNum = KWindowSystem::numberOfDesktops(); if (deskNum > 1) { int winDesk = KWindowInfo(mWindow, NET::WMDesktop).desktop(); QMenu* deskMenu = menu->addMenu(tr("To &Desktop")); a = deskMenu->addAction(tr("&All Desktops")); a->setData(NET::OnAllDesktops); a->setEnabled(winDesk != NET::OnAllDesktops); connect(a, SIGNAL(triggered(bool)), this, SLOT(moveApplicationToDesktop())); deskMenu->addSeparator(); for (int i = 0; i < deskNum; ++i) { a = deskMenu->addAction(tr("Desktop &%1").arg(i + 1)); a->setData(i + 1); a->setEnabled(i + 1 != winDesk); connect(a, SIGNAL(triggered(bool)), this, SLOT(moveApplicationToDesktop())); } int curDesk = KWindowSystem::currentDesktop(); a = menu->addAction(tr("&To Current Desktop")); a->setData(curDesk); a->setEnabled(curDesk != winDesk); connect(a, SIGNAL(triggered(bool)), this, SLOT(moveApplicationToDesktop())); } /********** Move/Resize **********/ menu->addSeparator(); a = menu->addAction(tr("&Move")); a->setEnabled(info.actionSupported(NET::ActionMove) && !(state & NET::Max) && !(state & NET::FullScreen)); connect(a, &QAction::triggered, this, &UKUITaskButton::moveApplication); a = menu->addAction(tr("Resi&ze")); a->setEnabled(info.actionSupported(NET::ActionResize) && !(state & NET::Max) && !(state & NET::FullScreen)); connect(a, &QAction::triggered, this, &UKUITaskButton::resizeApplication); /********** State menu **********/ menu->addSeparator(); a = menu->addAction(tr("Ma&ximize")); a->setEnabled(info.actionSupported(NET::ActionMax) && (!(state & NET::Max) || (state & NET::Hidden))); a->setData(NET::Max); connect(a, SIGNAL(triggered(bool)), this, SLOT(maximizeApplication())); if (event->modifiers() & Qt::ShiftModifier) { a = menu->addAction(tr("Maximize vertically")); a->setEnabled(info.actionSupported(NET::ActionMaxVert) && !((state & NET::MaxVert) || (state & NET::Hidden))); a->setData(NET::MaxVert); connect(a, SIGNAL(triggered(bool)), this, SLOT(maximizeApplication())); a = menu->addAction(tr("Maximize horizontally")); a->setEnabled(info.actionSupported(NET::ActionMaxHoriz) && !((state & NET::MaxHoriz) || (state & NET::Hidden))); a->setData(NET::MaxHoriz); connect(a, SIGNAL(triggered(bool)), this, SLOT(maximizeApplication())); } a = menu->addAction(tr("&Restore")); a->setEnabled((state & NET::Hidden) || (state & NET::Max) || (state & NET::MaxHoriz) || (state & NET::MaxVert)); connect(a, SIGNAL(triggered(bool)), this, SLOT(deMaximizeApplication())); a = menu->addAction(tr("Mi&nimize")); a->setEnabled(info.actionSupported(NET::ActionMinimize) && !(state & NET::Hidden)); connect(a, SIGNAL(triggered(bool)), this, SLOT(minimizeApplication())); if (state & NET::Shaded) { a = menu->addAction(tr("Roll down")); a->setEnabled(info.actionSupported(NET::ActionShade) && !(state & NET::Hidden)); connect(a, SIGNAL(triggered(bool)), this, SLOT(unShadeApplication())); } else { a = menu->addAction(tr("Roll up")); a->setEnabled(info.actionSupported(NET::ActionShade) && !(state & NET::Hidden)); connect(a, SIGNAL(triggered(bool)), this, SLOT(shadeApplication())); } /********** Layer menu **********/ menu->addSeparator(); QMenu* layerMenu = menu->addMenu(tr("&Layer")); a = layerMenu->addAction(tr("Always on &top")); // FIXME: There is no info.actionSupported(NET::ActionKeepAbove) a->setEnabled(!(state & NET::KeepAbove)); a->setData(NET::KeepAbove); connect(a, SIGNAL(triggered(bool)), this, SLOT(setApplicationLayer())); a = layerMenu->addAction(tr("&Normal")); a->setEnabled((state & NET::KeepAbove) || (state & NET::KeepBelow)); // FIXME: There is no NET::KeepNormal, so passing 0 a->setData(0); connect(a, SIGNAL(triggered(bool)), this, SLOT(setApplicationLayer())); a = layerMenu->addAction(tr("Always on &bottom")); // FIXME: There is no info.actionSupported(NET::ActionKeepBelow) a->setEnabled(!(state & NET::KeepBelow)); a->setData(NET::KeepBelow); connect(a, SIGNAL(triggered(bool)), this, SLOT(setApplicationLayer())); /********** Kill menu **********/ menu->addSeparator(); a = menu->addAction(QIcon::fromTheme("process-stop"), tr("&Close")); connect(a, SIGNAL(triggered(bool)), this, SLOT(closeApplication())); menu->setGeometry(mParentTaskBar->panel()->calculatePopupWindowPos(mapToGlobal(event->pos()), menu->sizeHint())); mPlugin->willShowWindow(menu); menu->show(); } /************************************************ ************************************************/ void UKUITaskButton::setUrgencyHint(bool set) { if (mUrgencyHint == set) return; if (!set) KWindowSystem::demandAttention(mWindow, false); mUrgencyHint = set; setProperty("urgent", set); style()->unpolish(this); style()->polish(this); update(); } bool UKUITaskButton::isOnDesktop(int desktop) const { return KWindowInfo(mWindow, NET::WMDesktop).isOnDesktop(desktop); } bool UKUITaskButton::isOnCurrentScreen() const { return QApplication::desktop()->screenGeometry(parentTaskBar()).intersects(KWindowInfo(mWindow, NET::WMFrameExtents).frameGeometry()); } bool UKUITaskButton::isMinimized() const { return KWindowInfo(mWindow,NET::WMState | NET::XAWMState).isMinimized(); } Qt::Corner UKUITaskButton::origin() const { return mOrigin; } void UKUITaskButton::setOrigin(Qt::Corner newOrigin) { if (mOrigin != newOrigin) { mOrigin = newOrigin; update(); } } void UKUITaskButton::setAutoRotation(bool value, IUKUIPanel::Position position) { if (value) { switch (position) { case IUKUIPanel::PositionTop: case IUKUIPanel::PositionBottom: setOrigin(Qt::TopLeftCorner); break; case IUKUIPanel::PositionLeft: setOrigin(Qt::BottomLeftCorner); break; case IUKUIPanel::PositionRight: setOrigin(Qt::TopRightCorner); break; } } else setOrigin(Qt::TopLeftCorner); } void UKUITaskButton::enterEvent(QEvent *) { taskbuttonstatus=HOVER; update(); } void UKUITaskButton::leaveEvent(QEvent *) { taskbuttonstatus=NORMAL; update(); } /*在paintEvent中执行绘图事件会造成高分屏下图片模糊 * 高分屏的图片模糊问题大概率与svg/png图片无关 * */ void UKUITaskButton::paintEvent(QPaintEvent *event) { QToolButton::paintEvent(event); return; /* QSize sz = size(); QSize adjSz =sz; QTransform transform; QPoint originPoint; switch (mOrigin) { case Qt::TopLeftCorner: transform.rotate(0.0); originPoint = QPoint(0.0, 0.0); break; case Qt::TopRightCorner: transform.rotate(90.0); originPoint = QPoint(0.0, -sz.width()); adjSz.transpose(); break; case Qt::BottomRightCorner: transform.rotate(180.0); originPoint = QPoint(-sz.width(), -sz.height()); break; case Qt::BottomLeftCorner: transform.rotate(270.0); originPoint = QPoint(-sz.height(), 0.0); adjSz.transpose(); break; } bool drawPixmapNextTime = false; if (!mDrawPixmap) { mPixmap = QPixmap(adjSz); mPixmap.fill(QColor(255, 0, 0, 0)); if (adjSz != sz) resize(adjSz); // this causes paint event to be repeated - next time we'll paint the pixmap to the widget surface. // copied from QToolButton::paintEvent { QStylePainter painter(&mPixmap, this); QStyleOptionToolButton opt; initStyleOption(&opt); painter.setBrush(QBrush(QColor(0xFF,0xFF,0xFF,0x19))); painter.drawComplexControl(QStyle::CC_ToolButton, opt); // } if (adjSz != sz) { resize(sz); drawPixmapNextTime = true; } else mDrawPixmap = true; // transfer the pixmap to the widget now! } if (mDrawPixmap) { QPainter painter(this); painter.setTransform(transform); painter.drawPixmap(originPoint, mPixmap); drawPixmapNextTime = false; } mDrawPixmap = drawPixmapNextTime; */ } bool UKUITaskButton::hasDragAndDropHover() const { return mDNDTimer->isActive(); } ukui-panel-3.0.6.4/plugin-taskbar-wayland/ukuitaskwidget.cpp0000644000175000017500000007314114204636772022525 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include "../panel/common/ukuisettings.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ukuitaskgroup.h" #include "ukuitaskbar.h" #include "ukuitaskclosebutton.h" #include // Necessary for closeApplication() #include #include bool UKUITaskWidget::sDraggging = false; /************************************************ ************************************************/ //void LeftAlignedTextStyle::drawItemText(QPainter * painter, const QRect & rect, int flags // , const QPalette & pal, bool enabled, const QString & text // , QPalette::ColorRole textRole) const //{ // QString txt = QFontMetrics(painter->font()).elidedText(text, Qt::ElideRight, rect.width()); // return QProxyStyle::drawItemText(painter, rect, (flags & ~Qt::AlignHCenter) | Qt::AlignLeft, pal, enabled, txt, textRole); //} /************************************************ ************************************************/ UKUITaskWidget::UKUITaskWidget(const WId window, UKUITaskBar * taskbar, QWidget *parent) : QWidget(parent), mWindow(window), mUrgencyHint(false), mOrigin(Qt::TopLeftCorner), mDrawPixmap(false), mParentTaskBar(taskbar), mPlugin(mParentTaskBar->plugin()), mDNDTimer(new QTimer(this)) { Q_ASSERT(taskbar); setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); setMinimumWidth(1); setMinimumHeight(1); setAcceptDrops(true); // QPixmap closePix = style()->standardPixmap(QStyle::SP_TitleBarCloseButton); status=NORMAL; setAttribute(Qt::WA_TranslucentBackground);//设置窗口背景透明 setWindowFlags(Qt::FramelessWindowHint); //设置无边框窗口 //for layout mCloseBtn = new UKUITaskCloseButton(mWindow, this); // mCloseBtn->setIcon(QIcon::fromTheme("window-close-symbolic")); mCloseBtn->setIconSize(QSize(19,19)); mCloseBtn->setFixedSize(QSize(19,19)); mTitleLabel = new QLabel(this); mTitleLabel->setMargin(0); // mTitleLabel->setContentsMargins(0,0,0,10); // mTitleLabel->adjustSize(); // mTitleLabel->setStyleSheet("QLabel{background-color: red;}"); mThumbnailLabel = new QLabel(this); mAppIcon = new QLabel(this); mVWindowsLayout = new QVBoxLayout(this); mTopBarLayout = new QHBoxLayout(this); mTopBarLayout->setContentsMargins(0,0,0,0); // mTopBarLayout->setAlignment(Qt::AlignVCenter); // mTopBarLayout->setDirection(QBoxLayout::LeftToRight); mTitleLabel->setAlignment(Qt::AlignLeft | Qt::AlignVCenter); mAppIcon->setAlignment(Qt::AlignLeft); mAppIcon->setScaledContents(false); // 自动缩放图片 // titleLabel->setScaledContents(true); mThumbnailLabel->setScaledContents(true); // 设置控件缩放方式 QSizePolicy sizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); sizePolicy.setHorizontalPolicy(QSizePolicy::Expanding); mTitleLabel->setSizePolicy(sizePolicy); mAppIcon->setSizePolicy(sizePolicy); sizePolicy.setVerticalPolicy(QSizePolicy::Expanding); // mTitleLabel->setAttribute(Qt::WA_TranslucentBackground, true); // mAppIcon->setAttribute(Qt::WA_TranslucentBackground, true); // mAppIcon->resize(QSize(32,32)); // 设置控件最大尺寸 //mTitleLabel->setFixedHeight(32); mTitleLabel->setMinimumWidth(1); mThumbnailLabel->setMinimumSize(QSize(1, 1)); mTitleLabel->setContentsMargins(0, 0, 5, 0); // mTopBarLayout->setSpacing(5); mTopBarLayout->addWidget(mAppIcon, 0, Qt::AlignLeft | Qt::AlignVCenter); mTopBarLayout->addWidget(mTitleLabel, 10, Qt::AlignLeft); mTopBarLayout->addWidget(mCloseBtn, 0, Qt::AlignRight); // mTopBarLayout->addStretch(); // mTopBarLayout->addWidget(mCloseBtn, 0, Qt::AlignRight | Qt::AlignVCenter); // mVWindowsLayout->setAlignment(Qt::AlignCenter); mVWindowsLayout->addLayout(mTopBarLayout); mVWindowsLayout->addWidget(mThumbnailLabel, Qt::AlignCenter, Qt::AlignCenter); mVWindowsLayout->setSizeConstraint(QLayout::SetMinAndMaxSize); this->setLayout(mVWindowsLayout); updateText(); updateIcon(); mDNDTimer->setSingleShot(true); mDNDTimer->setInterval(700); connect(mDNDTimer, SIGNAL(timeout()), this, SLOT(activateWithDraggable())); connect(UKUi::Settings::globalSettings(), SIGNAL(iconThemeChanged()), this, SLOT(updateIcon())); connect(mParentTaskBar, &UKUITaskBar::iconByClassChanged, this, &UKUITaskWidget::updateIcon); connect(mCloseBtn, SIGNAL(sigClicked()), this, SLOT(closeApplication())); connect(KWindowSystem::self(), static_cast(&KWindowSystem::windowChanged) , this, &UKUITaskWidget::updateIcon); } UKUITaskWidget::UKUITaskWidget(QString iconName, const WId window, UKUITaskBar * taskbar, QWidget *parent) : QWidget(parent), mParentTaskBar(taskbar), mWindow(window), mDNDTimer(new QTimer(this)) { isWaylandWidget = true; //setMinimumWidth(400); //setMinimumHeight(400); status=NORMAL; setAttribute(Qt::WA_TranslucentBackground);//设置窗口背景透明 setWindowFlags(Qt::FramelessWindowHint); //设置无边框窗口 //for layout mCloseBtn = new UKUITaskCloseButton(mWindow, this); // mCloseBtn->setIcon(QIcon::fromTheme("window-close-symbolic")); mCloseBtn->setIconSize(QSize(19,19)); mCloseBtn->setFixedSize(QSize(19,19)); mTitleLabel = new QLabel(this); mTitleLabel->setMargin(0); // mTitleLabel->setContentsMargins(0,0,0,10); // mTitleLabel->adjustSize(); // mTitleLabel->setStyleSheet("QLabel{background-color: red;}"); mThumbnailLabel = new QLabel(this); mAppIcon = new QLabel(this); mVWindowsLayout = new QVBoxLayout(this); mTopBarLayout = new QHBoxLayout(this); mTopBarLayout->setContentsMargins(0,0,0,0); // mTopBarLayout->setAlignment(Qt::AlignVCenter); // mTopBarLayout->setDirection(QBoxLayout::LeftToRight); mTitleLabel->setAlignment(Qt::AlignLeft | Qt::AlignVCenter); mAppIcon->setAlignment(Qt::AlignLeft); mAppIcon->setScaledContents(false); // 自动缩放图片 // titleLabel->setScaledContents(true); mThumbnailLabel->setScaledContents(true); // 设置控件缩放方式 QSizePolicy sizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); sizePolicy.setHorizontalPolicy(QSizePolicy::Expanding); mTitleLabel->setSizePolicy(sizePolicy); mAppIcon->setSizePolicy(sizePolicy); sizePolicy.setVerticalPolicy(QSizePolicy::Expanding); // mTitleLabel->setAttribute(Qt::WA_TranslucentBackground, true); // mAppIcon->setAttribute(Qt::WA_TranslucentBackground, true); // mAppIcon->resize(QSize(32,32)); // 设置控件最大尺寸 //mTitleLabel->setFixedHeight(32); mTitleLabel->setMinimumWidth(1); mThumbnailLabel->setMinimumSize(QSize(1, 1)); mThumbnailLabel->setMaximumSize(QSize(this->width()*2,this->height()*8)); mTitleLabel->setContentsMargins(0, 0, 5, 0); // mTopBarLayout->setSpacing(5); mTopBarLayout->addWidget(mAppIcon, 0, Qt::AlignLeft | Qt::AlignVCenter); mTopBarLayout->addWidget(mTitleLabel, 10, Qt::AlignLeft); mTopBarLayout->addWidget(mCloseBtn, 0, Qt::AlignRight); // mTopBarLayout->addStretch(); // mTopBarLayout->addWidget(mCloseBtn, 0, Qt::AlignRight | Qt::AlignVCenter); // mVWindowsLayout->setAlignment(Qt::AlignCenter); mVWindowsLayout->addLayout(mTopBarLayout); mVWindowsLayout->addWidget(mThumbnailLabel, Qt::AlignCenter, Qt::AlignCenter); mVWindowsLayout->setSizeConstraint(QLayout::SetMinAndMaxSize); this->setLayout(mVWindowsLayout); updateText(); updateIcon(); mDNDTimer->setSingleShot(true); mDNDTimer->setInterval(700); connect(mDNDTimer, SIGNAL(timeout()), this, SLOT(activateWithDraggable())); connect(UKUi::Settings::globalSettings(), SIGNAL(iconThemeChanged()), this, SLOT(updateIcon())); connect(mParentTaskBar, &UKUITaskBar::iconByClassChanged, this, &UKUITaskWidget::updateIcon); connect(mCloseBtn, SIGNAL(sigClicked()), this, SLOT(closeApplication())); } /************************************************ ************************************************/ UKUITaskWidget::~UKUITaskWidget() { this->deleteLater(); } /************************************************ ************************************************/ void UKUITaskWidget::wl_updateIcon(QString iconName){ mAppIcon->setPixmap(QIcon::fromTheme(iconName).pixmap(QSize(19,19))); } void UKUITaskWidget::wl_updateTitle(QString caption) { mTitleLabel->setText(caption); printf("\n%s\n", caption.toStdString().data()); QPalette pa; pa.setColor(QPalette::WindowText,Qt::white); mTitleLabel->setPalette(pa); } void UKUITaskWidget::updateText() { KWindowInfo info(mWindow, NET::WMVisibleName | NET::WMName); QString title = info.visibleName().isEmpty() ? info.name() : info.visibleName(); mTitleLabel->setText(title); QPalette pa; pa.setColor(QPalette::WindowText,Qt::white); mTitleLabel->setPalette(pa); // setText(title.replace("&", "&&")); // setToolTip(title); } /************************************************ ************************************************/ void UKUITaskWidget::updateIcon() { QIcon ico; if (mParentTaskBar->isIconByClass()) { ico = QIcon::fromTheme(QString::fromUtf8(KWindowInfo{mWindow, 0, NET::WM2WindowClass}.windowClassClass()).toLower()); } if (ico.isNull()) { ico = KWindowSystem::icon(mWindow); } mAppIcon->setPixmap(ico.pixmap(QSize(19,19))); setPixmap(KWindowSystem::icon(mWindow)); // mPixmap = ico.pixmap(QSize(64,64); //mAppIcon->setWindowIcon(ico.isNull() ? XdgIcon::defaultApplicationIcon() : ico); //setIcon(ico.isNull() ? XdgIcon::defaultApplicationIcon() : ico); } void UKUITaskWidget::setPixmap(QPixmap _pixmap) { mPixmap = _pixmap; } QPixmap UKUITaskWidget::getPixmap() { return mPixmap; } /************************************************ ************************************************/ void UKUITaskWidget::refreshIconGeometry(QRect const & geom) { NETWinInfo info(QX11Info::connection(), windowId(), (WId) QX11Info::appRootWindow(), NET::WMIconGeometry, 0); NETRect const curr = info.iconGeometry(); if (curr.pos.x != geom.x() || curr.pos.y != geom.y() || curr.size.width != geom.width() || curr.size.height != geom.height()) { NETRect nrect; nrect.pos.x = geom.x(); nrect.pos.y = geom.y(); nrect.size.height = geom.height(); nrect.size.width = geom.width(); info.setIconGeometry(nrect); } } /************************************************ ************************************************/ void UKUITaskWidget::dragEnterEvent(QDragEnterEvent *event) { // It must be here otherwise dragLeaveEvent and dragMoveEvent won't be called // on the other hand drop and dragmove events of parent widget won't be called event->acceptProposedAction(); if (event->mimeData()->hasFormat(mimeDataFormat())) { emit dragging(event->source(), event->pos()); setAttribute(Qt::WA_UnderMouse, false); } else { mDNDTimer->start(); } QWidget::dragEnterEvent(event); } void UKUITaskWidget::dragMoveEvent(QDragMoveEvent * event) { if (event->mimeData()->hasFormat(mimeDataFormat())) { emit dragging(event->source(), event->pos()); setAttribute(Qt::WA_UnderMouse, false); } } void UKUITaskWidget::dragLeaveEvent(QDragLeaveEvent *event) { mDNDTimer->stop(); QWidget::dragLeaveEvent(event); } void UKUITaskWidget::dropEvent(QDropEvent *event) { mDNDTimer->stop(); if (event->mimeData()->hasFormat(mimeDataFormat())) { emit dropped(event->source(), event->pos()); setAttribute(Qt::WA_UnderMouse, false); } QWidget::dropEvent(event); } /************************************************ ************************************************/ void UKUITaskWidget::mousePressEvent(QMouseEvent* event) { const Qt::MouseButton b = event->button(); if (Qt::LeftButton == b) { mDragStartPosition = event->pos(); } else if (Qt::MidButton == b && parentTaskBar()->closeOnMiddleClick()) closeApplication(); QWidget::mousePressEvent(event); } /************************************************ ************************************************/ void UKUITaskWidget::mouseReleaseEvent(QMouseEvent* event) { if (event->button() == Qt::LeftButton) { // if (isChecked()) // minimizeApplication(); // else QDBusMessage message = QDBusMessage::createSignal("/", "com.ukui.kwin", "request"); QList args; quint32 m_wid=windowId(); args.append(m_wid); args.append(WAYLAND_GROUP_HIDE); repaint(); message.setArguments(args); QDBusConnection::sessionBus().send(message); raiseApplication(); } status = NORMAL; update(); QWidget::mouseReleaseEvent(event); } /************************************************ ************************************************/ void UKUITaskWidget::enterEvent(QEvent *) { status = HOVER; mTitleLabel->setToolTip(mTitleLabel->text()); repaint(); } void UKUITaskWidget::leaveEvent(QEvent *) { status = NORMAL; repaint(); } QMimeData * UKUITaskWidget::mimeData() { QMimeData *mimedata = new QMimeData; QByteArray ba; QDataStream stream(&ba,QIODevice::WriteOnly); stream << (qlonglong)(mWindow); mimedata->setData(mimeDataFormat(), ba); return mimedata; } /************************************************ ************************************************/ void UKUITaskWidget::mouseMoveEvent(QMouseEvent* event) { } void UKUITaskWidget::closeGroup() { emit closeSigtoGroup(); } void UKUITaskWidget::contextMenuEvent(QContextMenuEvent *event) { if (!mPlugin || isWaylandWidget) return; QMenu * menu = new QMenu(tr("Widget")); menu->setAttribute(Qt::WA_DeleteOnClose); /* 对应预览图右键功能 关闭 还原 最大化 最小化 置顶 取消置顶*/ QAction *close = menu->addAction(QIcon::fromTheme("window-close-symbolic"), tr("close")); QAction *restore = menu->addAction(QIcon::fromTheme("window-restore-symbolic"), tr("restore")); QAction *maxim = menu->addAction(QIcon::fromTheme("window-maximize-symbolic"), tr("maximaze")); QAction *minim = menu->addAction(QIcon::fromTheme("window-minimize-symbolic"), tr("minimize")); QAction *above = menu->addAction(QIcon::fromTheme("ukui-fixed"), tr("above")); QAction *clear = menu->addAction(QIcon::fromTheme("ukui-unfixed"), tr("clear")); connect(close, SIGNAL(triggered()), this, SLOT(closeApplication())); connect(restore, SIGNAL(triggered()), this, SLOT(deMaximizeApplication())); connect(maxim, SIGNAL(triggered()), this, SLOT(maximizeApplication())); connect(minim, SIGNAL(triggered()), this, SLOT(minimizeApplication())); connect(above, SIGNAL(triggered()), this, SLOT(setWindowKeepAbove())); connect(clear, SIGNAL(triggered()), this, SLOT(setWindowStatusClear())); connect(menu, &QMenu::aboutToHide, [this] { emit closeSigtoPop(); }); KWindowInfo info(mWindow, NET::WMState); above->setEnabled(info.state() != NET::KeepAbove); clear->setEnabled(info.state() == NET::KeepAbove); menu->setGeometry(plugin()->panel()->calculatePopupWindowPos(mapToGlobal(event->pos()), menu->sizeHint())); plugin()->willShowWindow(menu); if (!isWaylandWidget) menu->show(); } /************************************************ ************************************************/ bool UKUITaskWidget::isApplicationHidden() const { KWindowInfo info(mWindow, NET::WMState); return (info.state() & NET::Hidden); } /************************************************ ************************************************/ bool UKUITaskWidget::isApplicationActive() const { return KWindowSystem::activeWindow() == mWindow; } /************************************************ ************************************************/ void UKUITaskWidget::activateWithDraggable() { // raise app in any time when there is a drag // in progress to allow drop it into an app raiseApplication(); KWindowSystem::forceActiveWindow(mWindow); } /************************************************ ************************************************/ void UKUITaskWidget::raiseApplication() { KWindowSystem::clearState(mWindow, NET::Hidden); if (isWaylandWidget) { QDBusMessage message = QDBusMessage::createSignal("/", "com.ukui.kwin", "request"); QList args; quint32 m_wid=windowId(); args.append(m_wid); args.append(WAYLAND_GROUP_ACTIVATE); repaint(); message.setArguments(args); QDBusConnection::sessionBus().send(message); emit windowMaximize(); setUrgencyHint(false); return; } KWindowInfo info(mWindow, NET::WMDesktop | NET::WMState | NET::XAWMState); if (parentTaskBar()->raiseOnCurrentDesktop() && info.isMinimized()) { KWindowSystem::setOnDesktop(mWindow, KWindowSystem::currentDesktop()); } else { int winDesktop = info.desktop(); if (KWindowSystem::currentDesktop() != winDesktop) KWindowSystem::setCurrentDesktop(winDesktop); } KWindowSystem::activateWindow(mWindow); emit windowMaximize(); setUrgencyHint(false); } /************************************************ ************************************************/ void UKUITaskWidget::minimizeApplication() { KWindowSystem::minimizeWindow(mWindow); } /************************************************ ************************************************/ void UKUITaskWidget::maximizeApplication() { QAction* act = qobject_cast(sender()); if (!act) return; int state = act->data().toInt(); switch (state) { case NET::MaxHoriz: KWindowSystem::setState(mWindow, NET::MaxHoriz); break; case NET::MaxVert: KWindowSystem::setState(mWindow, NET::MaxVert); break; default: KWindowSystem::setState(mWindow, NET::Max); break; } if (!isApplicationActive()) raiseApplication(); } /************************************************ ************************************************/ void UKUITaskWidget::deMaximizeApplication() { KWindowSystem::clearState(mWindow, NET::Max); if (!isApplicationActive()) raiseApplication(); } void UKUITaskWidget::setWindowKeepAbove() { KWindowSystem::setState(mWindow, NET::KeepAbove); } void UKUITaskWidget::setWindowStatusClear() { KWindowSystem::clearState(mWindow, NET::KeepAbove); } /************************************************ ************************************************/ void UKUITaskWidget::shadeApplication() { KWindowSystem::setState(mWindow, NET::Shaded); } /************************************************ ************************************************/ void UKUITaskWidget::unShadeApplication() { KWindowSystem::clearState(mWindow, NET::Shaded); } /************************************************ ************************************************/ //void UKUITaskWidget::priv_closeApplication() { //} void UKUITaskWidget::closeApplication() { // FIXME: Why there is no such thing in KWindowSystem?? if (isWaylandWidget) { QDBusMessage message = QDBusMessage::createSignal("/", "com.ukui.kwin", "request"); QList args; quint32 m_wid=windowId(); args.append(m_wid); args.append(WAYLAND_GROUP_CLOSE); message.setArguments(args); QDBusConnection::sessionBus().send(message); } NETRootInfo(QX11Info::connection(), NET::CloseWindow).closeWindowRequest(mWindow); } /************************************************ ************************************************/ void UKUITaskWidget::setApplicationLayer() { QAction* act = qobject_cast(sender()); if (!act) return; int layer = act->data().toInt(); switch(layer) { case NET::KeepAbove: KWindowSystem::clearState(mWindow, NET::KeepBelow); KWindowSystem::setState(mWindow, NET::KeepAbove); break; case NET::KeepBelow: KWindowSystem::clearState(mWindow, NET::KeepAbove); KWindowSystem::setState(mWindow, NET::KeepBelow); break; default: KWindowSystem::clearState(mWindow, NET::KeepBelow); KWindowSystem::clearState(mWindow, NET::KeepAbove); break; } } /************************************************ ************************************************/ void UKUITaskWidget::moveApplicationToDesktop() { QAction* act = qobject_cast(sender()); if (!act) return; bool ok; int desk = act->data().toInt(&ok); if (!ok) return; KWindowSystem::setOnDesktop(mWindow, desk); } /************************************************ ************************************************/ void UKUITaskWidget::moveApplication() { KWindowInfo info(mWindow, NET::WMDesktop); if (!info.isOnCurrentDesktop()) KWindowSystem::setCurrentDesktop(info.desktop()); if (isMinimized()) KWindowSystem::unminimizeWindow(mWindow); KWindowSystem::forceActiveWindow(mWindow); const QRect& g = KWindowInfo(mWindow, NET::WMGeometry).geometry(); int X = g.center().x(); int Y = g.center().y(); QCursor::setPos(X, Y); NETRootInfo(QX11Info::connection(), NET::WMMoveResize).moveResizeRequest(mWindow, X, Y, NET::Move); } /************************************************ ************************************************/ void UKUITaskWidget::resizeApplication() { KWindowInfo info(mWindow, NET::WMDesktop); if (!info.isOnCurrentDesktop()) KWindowSystem::setCurrentDesktop(info.desktop()); if (isMinimized()) KWindowSystem::unminimizeWindow(mWindow); KWindowSystem::forceActiveWindow(mWindow); const QRect& g = KWindowInfo(mWindow, NET::WMGeometry).geometry(); int X = g.bottomRight().x(); int Y = g.bottomRight().y(); QCursor::setPos(X, Y); NETRootInfo(QX11Info::connection(), NET::WMMoveResize).moveResizeRequest(mWindow, X, Y, NET::BottomRight); } /************************************************ ************************************************/ void UKUITaskWidget::setUrgencyHint(bool set) { if (mUrgencyHint == set) return; if (!set) KWindowSystem::demandAttention(mWindow, false); mUrgencyHint = set; setProperty("urgent", set); style()->unpolish(this); style()->polish(this); update(); } /************************************************ ************************************************/ bool UKUITaskWidget::isOnDesktop(int desktop) const { return KWindowInfo(mWindow, NET::WMDesktop).isOnDesktop(desktop); } bool UKUITaskWidget::isOnCurrentScreen() const { return QApplication::desktop()->screenGeometry(parentTaskBar()).intersects(KWindowInfo(mWindow, NET::WMFrameExtents).frameGeometry()); } bool UKUITaskWidget::isMinimized() const { // return KWindowInfo(mWindow,NET::WMState | NET::XAWMState).isMinimized(); #if (QT_VERSION >= QT_VERSION_CHECK(5,7,0)) return KWindowInfo(mWindow,NET::WMState | NET::XAWMState).isMinimized(); #else return isApplicationActive(); #endif } bool UKUITaskWidget::isFocusState() const { qDebug()<<"KWindowInfo(mWindow,NET::WMState).state():"<= QT_VERSION_CHECK(5,7,0)) return NET::Focused == (KWindowInfo(mWindow,NET::WMState).state()&NET::Focused); #else return isApplicationActive(); #endif } Qt::Corner UKUITaskWidget::origin() const { return mOrigin; } void UKUITaskWidget::setOrigin(Qt::Corner newOrigin) { if (mOrigin != newOrigin) { mOrigin = newOrigin; update(); } } void UKUITaskWidget::setAutoRotation(bool value, IUKUIPanel::Position position) { if (value) { switch (position) { case IUKUIPanel::PositionTop: case IUKUIPanel::PositionBottom: setOrigin(Qt::TopLeftCorner); break; case IUKUIPanel::PositionLeft: setOrigin(Qt::BottomLeftCorner); break; case IUKUIPanel::PositionRight: setOrigin(Qt::TopRightCorner); break; } } else setOrigin(Qt::TopLeftCorner); } void UKUITaskWidget::paintEvent(QPaintEvent *event) { /*旧的设置预览三态的方式,注释掉的原因是其未能设置阴影*/ #if 0 QStyleOption opt; opt.init(this); QPainter p(this); switch(status) { case NORMAL: { p.setBrush(QBrush(QColor(0x13,0x14,0x14,0xb2))); p.setPen(Qt::black); break; } case HOVER: { // p.setBrush(QBrush(QColor(0xFF,0xFF,0xFF,0x19))); p.setBrush(QBrush(QColor(0x13,0x14,0x14,0x19))); p.setPen(Qt::black); break; } case PRESS: { p.setBrush(QBrush(QColor(0xFF,0xFF,0xFF,0x19))); p.setPen(Qt::white); break; } } p.setRenderHint(QPainter::Antialiasing); // 反锯齿; p.drawRoundedRect(opt.rect,6,6); style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); #endif #if 1 /* * 预览图的设置阴影的方式与其他控件有所不同 * 由于涉及到UKUITaskWidget 中心是一张截图 * 此处设置阴影的方式不是一种通用的方式 * tr: * The way of setting shadow in preview image is different from other controls * As it involves UKUITaskWidget center is a screenshot * The way to set the shadow here is not a general way */ QPainter p(this); p.setRenderHint(QPainter::Antialiasing); QPainterPath rectPath; rectPath.addRoundedRect(this->rect(),6,6); // 画一个黑底 QPixmap pixmap(this->rect().size()); pixmap.fill(Qt::transparent); QPainter pixmapPainter(&pixmap); pixmapPainter.setRenderHint(QPainter::Antialiasing); pixmapPainter.drawPath(rectPath); pixmapPainter.end(); // 模糊这个黑底 extern void qt_blurImage(QImage &blurImage, qreal radius, bool quality, int transposed); QImage img = pixmap.toImage(); qt_blurImage(img, 10, false, false); // 挖掉中心 pixmap = QPixmap::fromImage(img); QPainter pixmapPainter2(&pixmap); pixmapPainter2.setRenderHint(QPainter::Antialiasing); pixmapPainter2.setCompositionMode(QPainter::CompositionMode_Clear); /*在Qt中定义了一个常量,用于设置透明的颜色,即Qt::transparent,表示RGBA值为(0,0,0,0)的透明色。*/ // pixmapPainter2.setPen(Qt::transparent); // pixmapPainter2.setBrush(Qt::transparent); pixmapPainter2.drawPath(rectPath); // 绘制阴影 p.drawPixmap(this->rect(), pixmap, pixmap.rect()); // 绘制底色 p.save(); switch(status) { case NORMAL: { p.fillPath(rectPath, QColor(0x13,0x14,0x14,0xb2)); break; } case HOVER: { p.fillPath(rectPath, QColor(0x13,0x14,0x14,0x66)); break; } case PRESS: { p.fillPath(rectPath, QColor(0xFF,0xFF,0xFF,0x19)); break; } } p.restore(); #endif } bool UKUITaskWidget::hasDragAndDropHover() const { return mDNDTimer->isActive(); } void UKUITaskWidget::updateTitle() { updateText(); } void UKUITaskWidget::setThumbNail(QPixmap _pixmap) { mThumbnailLabel->setPixmap(_pixmap); } void UKUITaskWidget::removeThumbNail() { if(mThumbnailLabel) { mVWindowsLayout->removeWidget(mThumbnailLabel); mThumbnailLabel->setParent(NULL); mThumbnailLabel->deleteLater(); mThumbnailLabel = NULL; } } void UKUITaskWidget::addThumbNail() { if(!mThumbnailLabel) { mThumbnailLabel = new QLabel(this); mThumbnailLabel->setScaledContents(true); mThumbnailLabel->setMinimumSize(QSize(1, 1)); // mVWindowsLayout->addLayout(mTopBarLayout, 100); mVWindowsLayout->addWidget(mThumbnailLabel, 0, Qt::AlignCenter); } else { return; } } void UKUITaskWidget::setTitleFixedWidth(int size) { mTitleLabel->setFixedWidth(size); mTitleLabel->adjustSize(); } int UKUITaskWidget::getWidth() { return mTitleLabel->width(); } void UKUITaskWidget::setThumbFixedSize(int w) { this->mThumbnailLabel->setFixedWidth(w); } void UKUITaskWidget::setThumbMaximumSize(int w) { this->mThumbnailLabel->setMaximumWidth(w); } void UKUITaskWidget::setThumbScale(bool val) { this->mThumbnailLabel->setScaledContents(val); } ukui-panel-3.0.6.4/plugin-taskbar-wayland/ukuigrouppopup.h0000644000175000017500000000470414204636772022243 0ustar fengfeng/* BEGIN_COMMON_COPYRIGHT_HEADER * (c)LGPL2+ * * Copyright: 2011 Razor team * 2014 LXQt team * Authors: * Alexander Sokoloff * Maciej Płaza * Kuzma Shapran * * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA * * END_COMMON_COPYRIGHT_HEADER */ #ifndef UKUITASKPOPUP_H #define UKUITASKPOPUP_H #include #include #include #include #include #include "ukuitaskbutton.h" #include "ukuitaskgroup.h" #include "ukuitaskbar.h" class UKUIGroupPopup: public QFrame { Q_OBJECT public: UKUIGroupPopup(UKUITaskGroup *group); ~UKUIGroupPopup(); void hide(bool fast = false); void show(); // Layout int indexOf(UKUITaskButton *button) { return layout()->indexOf(button); } int count() { return layout()->count(); } QLayoutItem * itemAt(int i) { return layout()->itemAt(i); } int spacing() { return layout()->spacing(); } void addButton(UKUITaskButton* button) { layout()->addWidget(button); } void removeWidget(QWidget *button) { layout()->removeWidget(button); } void pubcloseWindowDelay() { closeWindowDelay(); } protected: void dragEnterEvent(QDragEnterEvent * event); void dragLeaveEvent(QDragLeaveEvent *event); void dropEvent(QDropEvent * event); void leaveEvent(QEvent * event); void enterEvent(QEvent * event); void paintEvent(QPaintEvent * event); void mousePressEvent(QMouseEvent *event); void closeTimerSlot(); private: bool rightclick; UKUITaskGroup *mGroup; QTimer mCloseTimer; private slots: void killTimerDelay(); void closeWindowDelay(); }; #endif // UKUITASKPOPUP_H ukui-panel-3.0.6.4/ukui-flash-disk/0000755000175000017500000000000014204636772015367 5ustar fengfengukui-panel-3.0.6.4/ukui-flash-disk/flashdiskdata.cpp0000644000175000017500000006016114203402514020661 0ustar fengfeng/* * Copyright (C) 2021 KylinSoft Co., Ltd. * * Authors: * Yang Min yangmin@kylinos.cn * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include using namespace std; #include "flashdiskdata.h" FlashDiskData* FlashDiskData::m_instance = nullptr; QMutex FlashDiskData::m_mutex; FlashDiskData::FlashDiskData() { m_devInfoWithDrive.clear(); m_devInfoWithVolume.clear(); m_devInfoWithMount.clear(); } FlashDiskData::~FlashDiskData() { } FlashDiskData *FlashDiskData::getInstance() { if (m_instance == nullptr) { QMutexLocker locker(&m_mutex); if (m_instance == nullptr) { m_instance = new FlashDiskData(); } } return m_instance; } map& FlashDiskData::getDevInfoWithDrive() { return m_devInfoWithDrive; } map& FlashDiskData::getDevInfoWithVolume() { return m_devInfoWithVolume; } map& FlashDiskData::getDevInfoWithMount() { return m_devInfoWithMount; } int FlashDiskData::addDriveInfo(FDDriveInfo driveInfo) { if (driveInfo.strId.empty()) { return -1; } map::iterator itVolumeInfoNew = driveInfo.listVolumes.begin(); for (; itVolumeInfoNew != driveInfo.listVolumes.end(); itVolumeInfoNew++) { if (!itVolumeInfoNew->second.strId.empty()) { map::iterator itVolumeInfo = m_devInfoWithVolume.find(itVolumeInfoNew->second.strId); if (itVolumeInfo != m_devInfoWithVolume.end()) { m_devInfoWithVolume.erase(itVolumeInfo); } } } m_devInfoWithDrive[driveInfo.strId] = driveInfo; return 0; } int FlashDiskData::addVolumeInfoWithDrive(FDDriveInfo driveInfo, FDVolumeInfo volumeInfo) { if (driveInfo.strId.empty() || volumeInfo.strId.empty()) { return -1; } volumeInfo.mountInfo.lluMountTick = QDateTime::currentDateTime().toMSecsSinceEpoch(); map::iterator itVolumeInfo = m_devInfoWithVolume.find(volumeInfo.strId); if (itVolumeInfo != m_devInfoWithVolume.end()) { m_devInfoWithVolume.erase(itVolumeInfo); } map::iterator itDriveInfo = m_devInfoWithDrive.find(driveInfo.strId); if (itDriveInfo != m_devInfoWithDrive.end()) { itDriveInfo->second.listVolumes[volumeInfo.strId] = volumeInfo; } else { driveInfo.listVolumes.clear(); driveInfo.listVolumes[volumeInfo.strId] = volumeInfo; m_devInfoWithDrive[driveInfo.strId] = driveInfo; } return 0; } int FlashDiskData::addMountInfoWithDrive(FDDriveInfo driveInfo, FDVolumeInfo volumeInfo, FDMountInfo mountInfo) { if (driveInfo.strId.empty() || mountInfo.strId.empty()) { return -1; } mountInfo.lluMountTick = QDateTime::currentDateTime().toMSecsSinceEpoch(); map::iterator itDriveInfo = m_devInfoWithDrive.find(driveInfo.strId); if (itDriveInfo != m_devInfoWithDrive.end()) { volumeInfo.mountInfo = mountInfo; if (volumeInfo.strId.empty()) { itDriveInfo->second.listVolumes[mountInfo.strId] = volumeInfo; } else { itDriveInfo->second.listVolumes[volumeInfo.strId] = volumeInfo; } } else { driveInfo.listVolumes.clear(); volumeInfo.mountInfo = mountInfo; if (volumeInfo.strId.empty()) { driveInfo.listVolumes[mountInfo.strId] = volumeInfo; } else { driveInfo.listVolumes[volumeInfo.strId] = volumeInfo; } m_devInfoWithDrive[driveInfo.strId] = driveInfo; } return 0; } int FlashDiskData::addVolumeInfo(FDVolumeInfo volumeInfo) { if (volumeInfo.strId.empty()) { return -1; } volumeInfo.mountInfo.lluMountTick = QDateTime::currentDateTime().toMSecsSinceEpoch(); map::iterator itDriveInfo = m_devInfoWithDrive.begin(); for (; itDriveInfo != m_devInfoWithDrive.end(); itDriveInfo++) { if (itDriveInfo->second.listVolumes.find(volumeInfo.strId) != itDriveInfo->second.listVolumes.end()) { itDriveInfo->second.listVolumes[volumeInfo.strId] = volumeInfo; return 1; } } if (!volumeInfo.mountInfo.strId.empty()) { map::iterator itMountInfo = m_devInfoWithMount.find(volumeInfo.mountInfo.strId); if (itMountInfo != m_devInfoWithMount.end()) { m_devInfoWithMount.erase(itMountInfo); } } m_devInfoWithVolume[volumeInfo.strId] = volumeInfo; return 0; } int FlashDiskData::addMountInfo(FDMountInfo mountInfo) { if (mountInfo.strId.empty()) { return -1; } mountInfo.lluMountTick = QDateTime::currentDateTime().toMSecsSinceEpoch(); map::iterator itVolumeInfo = m_devInfoWithVolume.begin(); for (; itVolumeInfo != m_devInfoWithVolume.end(); itVolumeInfo++) { if (itVolumeInfo->second.mountInfo.strId == mountInfo.strId) { return 1; } } map::iterator itDriveInfo = m_devInfoWithDrive.begin(); for (; itDriveInfo != m_devInfoWithDrive.end(); itDriveInfo++) { itVolumeInfo = itDriveInfo->second.listVolumes.begin(); for (; itVolumeInfo != itDriveInfo->second.listVolumes.end(); itVolumeInfo++) { if (itVolumeInfo->second.mountInfo.strId == mountInfo.strId) { return 1; } } } m_devInfoWithMount[mountInfo.strId] = mountInfo; return 0; } int FlashDiskData::removeDriveInfo(FDDriveInfo driveInfo) { if (driveInfo.strId.empty()) { return -1; } if (m_devInfoWithDrive.find(driveInfo.strId) != m_devInfoWithDrive.end()) { if (getAttachedVolumeCount(driveInfo.strId) > 0) { Q_EMIT notifyDeviceRemoved(QString::fromStdString(driveInfo.strId)); } m_devInfoWithDrive.erase(driveInfo.strId); return 0; } return 1; } int FlashDiskData::removeVolumeInfo(FDVolumeInfo volumeInfo) { if (volumeInfo.strId.empty()) { return -1; } if (m_devInfoWithVolume.find(volumeInfo.strId) != m_devInfoWithVolume.end()) { if (getAttachedVolumeCount(volumeInfo.strId) == 1) { Q_EMIT notifyDeviceRemoved(QString::fromStdString(volumeInfo.strId)); } m_devInfoWithVolume.erase(volumeInfo.strId); return 0; } else { map::iterator itDriveInfo = m_devInfoWithDrive.begin(); for (; itDriveInfo != m_devInfoWithDrive.end(); itDriveInfo++) { map::iterator itVolumeInfo = itDriveInfo->second.listVolumes.find(volumeInfo.strId); if (itVolumeInfo != itDriveInfo->second.listVolumes.end()) { if (getAttachedVolumeCount(volumeInfo.strId) == 1) { Q_EMIT notifyDeviceRemoved(QString::fromStdString(volumeInfo.strId)); } if (itVolumeInfo->second.mountInfo.strId.empty()) { itDriveInfo->second.listVolumes.erase(volumeInfo.strId); } else { itVolumeInfo->second.strId = ""; } return 0; } } } return 1; } int FlashDiskData::removeMountInfo(FDMountInfo mountInfo) { if (mountInfo.strId.empty()) { return -1; } if (m_devInfoWithMount.find(mountInfo.strId) != m_devInfoWithMount.end()) { m_devInfoWithMount.erase(mountInfo.strId); return 0; } else { map::iterator itVolumeInfo = m_devInfoWithVolume.begin(); for (; itVolumeInfo != m_devInfoWithVolume.end(); itVolumeInfo++) { if (itVolumeInfo->second.mountInfo.strId == mountInfo.strId) { #if 0 FDMountInfo mountTemp; itVolumeInfo->second.mountInfo = mountTemp; if (itVolumeInfo->second.strId.empty()) { m_devInfoWithVolume.erase(itVolumeInfo); } #else // if (getAttachedVolumeCount(itVolumeInfo->second.strId) == 1) { // Q_EMIT notifyDeviceRemoved(QString::fromStdString(itVolumeInfo->second.strId)); // } // m_devInfoWithVolume.erase(itVolumeInfo); itVolumeInfo->second.mountInfo.strId = ""; #endif return 0; } } map::iterator itDriveInfo = m_devInfoWithDrive.begin(); for (; itDriveInfo != m_devInfoWithDrive.end(); itDriveInfo++) { itVolumeInfo = itDriveInfo->second.listVolumes.begin(); for (; itVolumeInfo != itDriveInfo->second.listVolumes.end(); itVolumeInfo++) { if (itVolumeInfo->second.mountInfo.strId == mountInfo.strId) { #if 0 FDMountInfo mountTemp; itVolumeInfo->second.mountInfo = mountTemp; if (itVolumeInfo->second.strId.empty()) { itDriveInfo->second.listVolumes.erase(itVolumeInfo); } #else // if (getAttachedVolumeCount(itVolumeInfo->second.strId) == 1) { // Q_EMIT notifyDeviceRemoved(QString::fromStdString(itVolumeInfo->second.strId)); // } // itDriveInfo->second.listVolumes.erase(itVolumeInfo); itVolumeInfo->second.mountInfo.strId = ""; #endif return 0; } } } } return 1; } bool FlashDiskData::isMountInfoExist(FDMountInfo mountInfo) { if (mountInfo.strId.empty()) { return false; } if (m_devInfoWithMount.find(mountInfo.strId) != m_devInfoWithMount.end()) { return true; } map::iterator itDriveInfo; map::iterator itVolumeInfo; itVolumeInfo = m_devInfoWithVolume.begin(); for (; itVolumeInfo != m_devInfoWithVolume.end(); itVolumeInfo++) { if (itVolumeInfo->second.mountInfo.strId == mountInfo.strId) { return true; } } itDriveInfo = m_devInfoWithDrive.begin(); for (; itDriveInfo != m_devInfoWithDrive.end(); itDriveInfo++) { itVolumeInfo = itDriveInfo->second.listVolumes.begin(); for (; itVolumeInfo != itDriveInfo->second.listVolumes.end(); itVolumeInfo++) { if (itVolumeInfo->second.mountInfo.strId == mountInfo.strId) { return true; } } } return false; } quint64 FlashDiskData::getMountTickDiff(FDMountInfo mountInfo) { quint64 curTick = QDateTime::currentDateTime().toMSecsSinceEpoch(); if (mountInfo.strId.empty()) { return 0; } if (m_devInfoWithMount.find(mountInfo.strId) != m_devInfoWithMount.end()) { return (curTick-m_devInfoWithMount[mountInfo.strId].lluMountTick); } map::iterator itDriveInfo; map::iterator itVolumeInfo; itVolumeInfo = m_devInfoWithVolume.begin(); for (; itVolumeInfo != m_devInfoWithVolume.end(); itVolumeInfo++) { if (itVolumeInfo->second.mountInfo.strId == mountInfo.strId) { return (curTick-itVolumeInfo->second.mountInfo.lluMountTick); } } itDriveInfo = m_devInfoWithDrive.begin(); for (; itDriveInfo != m_devInfoWithDrive.end(); itDriveInfo++) { itVolumeInfo = itDriveInfo->second.listVolumes.begin(); for (; itVolumeInfo != itDriveInfo->second.listVolumes.end(); itVolumeInfo++) { if (itVolumeInfo->second.mountInfo.strId == mountInfo.strId) { return (curTick-itVolumeInfo->second.mountInfo.lluMountTick); } } } return 0; } bool FlashDiskData::getVolumeInfoByMount(FDMountInfo mountInfo, FDVolumeInfo& volumeInfo) { quint64 curTick = QDateTime::currentDateTime().toMSecsSinceEpoch(); if (mountInfo.strId.empty()) { return false; } if (m_devInfoWithMount.find(mountInfo.strId) != m_devInfoWithMount.end()) { return false; } map::iterator itDriveInfo; map::iterator itVolumeInfo; itVolumeInfo = m_devInfoWithVolume.begin(); for (; itVolumeInfo != m_devInfoWithVolume.end(); itVolumeInfo++) { if (itVolumeInfo->second.mountInfo.strId == mountInfo.strId) { volumeInfo = itVolumeInfo->second; return true; } } itDriveInfo = m_devInfoWithDrive.begin(); for (; itDriveInfo != m_devInfoWithDrive.end(); itDriveInfo++) { itVolumeInfo = itDriveInfo->second.listVolumes.begin(); for (; itVolumeInfo != itDriveInfo->second.listVolumes.end(); itVolumeInfo++) { if (itVolumeInfo->second.mountInfo.strId == mountInfo.strId) { volumeInfo = itVolumeInfo->second; return true; } } } return false; } void FlashDiskData::resetAllNewState() { map::iterator itMountInfo = m_devInfoWithMount.begin(); for (; itMountInfo != m_devInfoWithMount.end(); itMountInfo++) { if (!itMountInfo->second.strId.empty()) { itMountInfo->second.isNewInsert = false; } } map::iterator itVolumeInfo = m_devInfoWithVolume.begin(); for (; itVolumeInfo != m_devInfoWithVolume.end(); itVolumeInfo++) { itVolumeInfo->second.isNewInsert = false; if (!itVolumeInfo->second.mountInfo.strId.empty()) { itVolumeInfo->second.mountInfo.isNewInsert = false; } } map::iterator itDriveInfo = m_devInfoWithDrive.begin(); for (; itDriveInfo != m_devInfoWithDrive.end(); itDriveInfo++) { itVolumeInfo = itDriveInfo->second.listVolumes.begin(); for (; itVolumeInfo != itDriveInfo->second.listVolumes.end(); itVolumeInfo++) { itVolumeInfo->second.isNewInsert = false; if (!itVolumeInfo->second.mountInfo.strId.empty()) { itVolumeInfo->second.mountInfo.isNewInsert = false; } } } } unsigned FlashDiskData::getValidInfoCount() { unsigned uDriveCount = 0; unsigned uVolumeCount = 0; unsigned uMountCount = 0; uMountCount = m_devInfoWithMount.size(); map::iterator itVolumeInfo = m_devInfoWithVolume.begin(); for (; itVolumeInfo != m_devInfoWithVolume.end(); itVolumeInfo++) { if (!itVolumeInfo->second.mountInfo.strId.empty()) { uVolumeCount ++; } } map::iterator itDriveInfo = m_devInfoWithDrive.begin(); for (; itDriveInfo != m_devInfoWithDrive.end(); itDriveInfo++) { itVolumeInfo = itDriveInfo->second.listVolumes.begin(); for (; itVolumeInfo != itDriveInfo->second.listVolumes.end(); itVolumeInfo++) { if (!itVolumeInfo->second.mountInfo.strId.empty()) { uDriveCount ++; } } } return uDriveCount + uVolumeCount + uMountCount; } unsigned FlashDiskData::getAttachedVolumeCount(string strId) { if (strId.empty()) { return 0; } map::iterator itVolumeInfo = m_devInfoWithVolume.begin(); for (; itVolumeInfo != m_devInfoWithVolume.end(); itVolumeInfo++) { if (itVolumeInfo->second.strId == strId) { return 1; } } map::iterator itDriveInfo = m_devInfoWithDrive.begin(); for (; itDriveInfo != m_devInfoWithDrive.end(); itDriveInfo++) { if (itDriveInfo->second.strId == strId) { return itDriveInfo->second.listVolumes.size(); } else { itVolumeInfo = itDriveInfo->second.listVolumes.begin(); for (; itVolumeInfo != itDriveInfo->second.listVolumes.end(); itVolumeInfo++) { if (itVolumeInfo->second.strId == strId) { return itDriveInfo->second.listVolumes.size(); } } } } return 0; } static bool strEndsWith(string s, string sub) { if (s.rfind(sub)==(s.length()-sub.length())) { return true; } else { return false; } } static bool strStartsWith(string s, string sub) { if (s.rfind(sub)==(s.length()-sub.length())) { return true; } else { return false; } } QString FlashDiskData::getVolumeIcon(QString strVolumeId) { QString strVolumeIcon = "drive-removable-media-usb"; quint64 mountSize = 0; map::iterator itVolumeInfo = m_devInfoWithVolume.begin(); for (; itVolumeInfo != m_devInfoWithVolume.end(); itVolumeInfo++) { if (itVolumeInfo->second.strId.find(strVolumeId.toStdString()) == 0) { strVolumeIcon = QString::fromStdString(itVolumeInfo->second.strIconPath); if (!itVolumeInfo->second.mountInfo.strId.empty()) { mountSize = itVolumeInfo->second.mountInfo.lluTotalSize; // if (!itVolumeInfo->second.mountInfo.strIconPath.empty()) { // if (strEndsWith(itVolumeInfo->second.mountInfo.strIconPath, ".ico")) { // strVolumeIcon = QString::fromStdString(itVolumeInfo->second.mountInfo.strIconPath); // } // } } break; } } if (strVolumeIcon == "drive-removable-media-usb") { map::iterator itDriveInfo = m_devInfoWithDrive.begin(); for (; itDriveInfo != m_devInfoWithDrive.end(); itDriveInfo++) { itVolumeInfo = itDriveInfo->second.listVolumes.begin(); for (; itVolumeInfo != itDriveInfo->second.listVolumes.end(); itVolumeInfo++) { if (itVolumeInfo->second.strId.find(strVolumeId.toStdString()) == 0) { strVolumeIcon = QString::fromStdString(itVolumeInfo->second.strIconPath); if (!itVolumeInfo->second.mountInfo.strId.empty()) { mountSize = itVolumeInfo->second.mountInfo.lluTotalSize; // if (!itVolumeInfo->second.mountInfo.strIconPath.empty()) { // if (strEndsWith(itVolumeInfo->second.mountInfo.strIconPath, ".ico")) { // strVolumeIcon = QString::fromStdString(itVolumeInfo->second.mountInfo.strIconPath); // } // } } break; } } } } if (strVolumeIcon != "drive-harddisk-usb") { return strVolumeIcon; } if (mountSize/(1024 * 1024 *1024) > 128) strVolumeIcon = "drive-harddisk-usb"; else strVolumeIcon = "drive-removable-media-usb"; return strVolumeIcon; } void FlashDiskData::clearAllData() { } void FlashDiskData::OutputInfos() { #if 0 unsigned uDriveCount = 0; unsigned uVolumeCount = 0; unsigned uMountCount = 0; uMountCount = m_devInfoWithMount.size(); uVolumeCount = m_devInfoWithVolume.size(); map::iterator itDriveInfo = m_devInfoWithDrive.begin(); for (; itDriveInfo != m_devInfoWithDrive.end(); itDriveInfo++) { uDriveCount += itDriveInfo->second.listVolumes.size(); } qDebug()<<"info count:"<::iterator itMountInfo = m_devInfoWithMount.begin(); for (; itMountInfo != m_devInfoWithMount.end(); itMountInfo++) { if (!itMountInfo->second.strId.empty()) { qDebug()<<"Mount:"<second.strId)<<"|" <second.strName)<<"|"<second.isCanUnmount <<"|"<second.isCanEject<<"|"<second.strTooltip)<<"|" <second.strUri)<<"|"<second.isNativeDev <<"|"<second.lluTotalSize<<"|"<second.isNewInsert<<"|"<second.lluMountTick <<"|"<second.strIconPath.c_str(); } } qDebug()<<"--------------------------------------------------------"; map::iterator itVolumeInfo = m_devInfoWithVolume.begin(); for (; itVolumeInfo != m_devInfoWithVolume.end(); itVolumeInfo++) { qDebug()<<"Volume:"<second.strId)<<"|" <second.strName)<<"|"<second.isCanMount <<"|"<second.isShouldAutoMount<<"|"<second.isCanEject <<"|"<second.strDevName)<<"|"<second.isNewInsert <<"|"<second.strIconPath.c_str(); if (!itVolumeInfo->second.mountInfo.strId.empty()) { qDebug()<<"Mount:"<second.mountInfo.strId)<<"|" <second.mountInfo.strName)<<"|"<second.mountInfo.isCanUnmount <<"|"<second.mountInfo.isCanEject<<"|"<second.mountInfo.strTooltip)<<"|" <second.mountInfo.strUri)<<"|"<second.mountInfo.isNativeDev <<"|"<second.mountInfo.lluTotalSize<<"|"<second.mountInfo.isNewInsert<<"|" <second.mountInfo.lluMountTick<<"|"<second.mountInfo.strIconPath.c_str(); } } qDebug()<<"--------------------------------------------------------"; itDriveInfo = m_devInfoWithDrive.begin(); for (; itDriveInfo != m_devInfoWithDrive.end(); itDriveInfo++) { qDebug()<<"Drive:"<second.strId)<<"|" <second.strName)<<"|"<second.isCanEject <<"|"<second.isRemovable<<"|"<second.isCanStart<<"|"<second.isCanStop <<"|"<second.strIconPath.c_str(); itVolumeInfo = itDriveInfo->second.listVolumes.begin(); for (; itVolumeInfo != itDriveInfo->second.listVolumes.end(); itVolumeInfo++) { qDebug()<<"Volume:"<second.strId)<<"|" <second.strName)<<"|"<second.isCanMount <<"|"<second.isShouldAutoMount<<"|"<second.isCanEject <<"|"<second.strDevName)<<"|"<second.isNewInsert <<"|"<second.strIconPath.c_str(); if (!itVolumeInfo->second.mountInfo.strId.empty()) { qDebug()<<"Mount:"<second.mountInfo.strId)<<"|" <second.mountInfo.strName)<<"|"<second.mountInfo.isCanUnmount <<"|"<second.mountInfo.isCanEject<<"|"<second.mountInfo.strTooltip)<<"|" <second.mountInfo.strUri)<<"|"<second.mountInfo.isNativeDev <<"|"<second.mountInfo.lluTotalSize<<"|"<second.mountInfo.isNewInsert<<"|" <second.mountInfo.lluMountTick<<"|"<second.mountInfo.strIconPath.c_str(); } } } qDebug()<<"+++++++++++++++++++++++++++++++++++++++++++++++++++++++++"; #endif } ukui-panel-3.0.6.4/ukui-flash-disk/interactivedialog.h0000644000175000017500000000406114203402514021216 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include QT_BEGIN_NAMESPACE namespace Ui { class interactiveDialog; } QT_END_NAMESPACE class interactiveDialog: public QWidget { Q_OBJECT public: interactiveDialog(QString strDevId, QWidget *parent); ~interactiveDialog(); private: QPushButton *chooseBtnContinue = nullptr; QPushButton *chooseBtnCancle = nullptr; QLabel *contentLable = nullptr; QHBoxLayout *content_H_BoxLayout = nullptr; QHBoxLayout *chooseBtn_H_BoxLayout = nullptr; QVBoxLayout *main_V_BoxLayout = nullptr; double m_transparency; int fontSize; QGSettings *m_transparency_gsettings = nullptr; QGSettings *gsetting = nullptr; private: void initWidgets(); void moveChooseDialogRight(); void initTransparentState(); void getTransparentData(); protected: void paintEvent(QPaintEvent *event); public Q_SLOTS: void convert(); Q_SIGNALS: void FORCESIG(); private: QString m_strDevId; }; #endif ukui-panel-3.0.6.4/ukui-flash-disk/gpartedinterface.h0000644000175000017500000000357014203402514021034 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include QT_BEGIN_NAMESPACE namespace Ui { class gpartedInterface; } QT_END_NAMESPACE class gpartedInterface: public QWidget { Q_OBJECT public: gpartedInterface(QWidget *parent); ~gpartedInterface(); private: double m_transparency; QGSettings *m_transparency_gsettings = nullptr; QGSettings *gsetting = nullptr; QPushButton *okButton; QLabel *noticeLabel; QHBoxLayout *notice_H_BoxLayout = nullptr; QHBoxLayout *button_H_BoxLayout = nullptr; QVBoxLayout *main_V_BoxLayout = nullptr; private: void initWidgets(); void moveChooseDialogRight(); void initTransparentState(); void getTransparentData(); protected: void paintEvent(QPaintEvent *event); }; #endif //GPARTEDINTERFAC_H ukui-panel-3.0.6.4/ukui-flash-disk/fdapplication.cpp0000644000175000017500000000223614203402514020673 0ustar fengfeng/* * Copyright (C) 2021 KylinSoft Co., Ltd. * * Authors: * Yang Min yangmin@kylinos.cn * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; #include "qclickwidget.h" #include "UnionVariable.h" #include "ejectInterface.h" #include "mainwindow.h" #include "MacroFile.h" #include "flashdiskdata.h" #include "fdclickwidget.h" #include "repair-dialog-box.h" namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); public: QSystemTrayIcon *m_systray; ejectInterface *m_eject = nullptr; interactiveDialog *chooseDialog = nullptr; bool ifSucess; int flagType; int driveMountNum; vector m_vtDeviveId; EjectDeviceInfo m_curEjectDeviceInfo; void MainWindowShow(bool isUpdate = false); void initTransparentState(); void initThemeMode(); void getTransparentData(); int getPanelPosition(QString str); int getPanelHeight(QString str); protected: void hideEvent(QHideEvent event); void resizeEvent(QResizeEvent *event); bool eventFilter(QObject *obj, QEvent *event); void paintEvent(QPaintEvent *event); private: Ui::MainWindow *ui; QVBoxLayout *vboxlayout; QLabel *no_device_label; QPushButton *eject_image_button; char *UDiskPathDis1; char *UDiskPathDis2; char *UDiskPathDis3; char *UDiskPathDis4; quint64 totalDis1; quint64 totalDis2; quint64 totalDis3; quint64 totalDis4; QClickWidget *open_widget; FDClickWidget *m_fdClickWidget; int hign; int VolumeNum; QTimer *interfaceHideTime; int num = 0; QScreen *screen; int triggerType = 0; //detective the type of MainWinow(insert USB disk or click systemtray icon) double m_transparency; QString currentThemeMode; QGSettings *m_transparency_gsettings = nullptr; QWidget *line = nullptr; bool ifautoload; bool insertorclick; QGSettings * ifsettings = nullptr; int telephoneNum; QString tmpPath; bool findPointMount; int driveVolumeNum; FlashDiskData* m_dataFlashDisk = nullptr; bool m_bIsMouseInTraIcon = false; bool m_bIsMouseInCentral = false; qint64 m_nAppStartTimestamp = 0; // 进程启动时的时间戳 QString m_strSysRootDev; bool mIsrunning = false; QMap mRepairDialog; void initFlashDisk(); void initSlots(); void newarea(int No, GDrive *Drive, GVolume *Volume, QString Drivename, QString nameDis1, QString nameDis2, QString nameDis3, QString nameDis4, qlonglong capacityDis1, qlonglong capacityDis2, qlonglong capacityDis3, qlonglong capacityDis4, QString pathDis1, QString pathDis2, QString pathDis3, QString pathDis4, int linestatus); void newarea(unsigned uDiskNo, QString strDriveId, QString strVolumeId, QString strMountId, QString driveName, QString volumeName, quint64 capacityDis, QString strMountUri, int linestatus); void moveBottomRight(); void moveBottomDirect(GDrive *drive); void moveBottomNoBase(); QString size_human(qlonglong capacity); void getDeviceInfo(); static void frobnitz_result_func_volume(GVolume *source_object,GAsyncResult *res,MainWindow *p_this); static void frobnitz_result_func_mount(GMount *source_object,GAsyncResult *res,MainWindow *p_this); //static void frobnitz_result_func_volume(GVolume *source_object,GAsyncResult *res,gpointer); static void drive_connected_callback (GVolumeMonitor *monitor, GDrive *drive, MainWindow *p_this); static void drive_disconnected_callback (GVolumeMonitor *monitor, GDrive *drive, MainWindow *p_this); static void volume_added_callback (GVolumeMonitor *monitor, GVolume *volume, MainWindow *p_this); static void volume_removed_callback (GVolumeMonitor *monitor, GVolume *volume, MainWindow *p_this); static void mount_added_callback (GVolumeMonitor *monitor, GMount *mount, MainWindow *p_this); static void mount_removed_callback (GVolumeMonitor *monitor, GMount *mount, MainWindow *p_this); void ifgetPinitMount(); static void frobnitz_force_result_func(GDrive *source_object,GAsyncResult *res,MainWindow *p_this); static void frobnitz_result_func(GDrive *source_object,GAsyncResult *res,MainWindow *p_this); static void frobnitz_normal_result_volume_eject(GVolume *source_object,GAsyncResult *res,MainWindow *p_this); static void frobnitz_force_result_unmount(GMount *source_object,GAsyncResult *res,MainWindow *p_this); static void AsyncUnmount(QString strMountRoot,MainWindow *p_this); void getSystemRootDev(); bool isSystemRootDev(QString strDev); bool doRealEject(EjectDeviceInfo* peDeviceInfo, GMountUnmountFlags flag); static GAsyncReadyCallback fileEjectMountableCB(GFile *file, GAsyncResult *res, EjectDeviceInfo *peDeviceInfo); static void driveStopCb(GObject* object, GAsyncResult* res, EjectDeviceInfo *peDeviceInfo); bool getDataCDRomCapacity(QString strDevId, quint64 &totalCapacity); void getDriveIconsInfo(GDrive* drive, FDDriveInfo& driveInfo); void getVolumeIconsInfo(GVolume* volume, FDVolumeInfo& volumeInfo); void getMountIconsInfo(GMount* mount, FDMountInfo& mountInfo); public Q_SLOTS: void iconActivated(QSystemTrayIcon::ActivationReason reason); void onConvertShowWindow(QString strDriveId, QString strMountUri); void onConvertUpdateWindow(QString strDevName, unsigned uDevType); void onMaininterfacehide(); void on_clickPanelToHideInterface(); void onRequestSendDesktopNotify(QString message, QString strIcon); void onInsertAbnormalDiskNotify(QString message); void onNotifyWnd(QObject* obj, QEvent *event); void onClickedEject(EjectDeviceInfo eDeviceInfo); void onRemountVolume(FDVolumeInfo volumeInfo); void onCheckDriveValid(FDDriveInfo driveInfo); bool onDeviceErrored(GDrive* drive); void onMountVolume(GVolume*); void onEjectVolumeForce(GVolume* v); // A fix pops up if the mount fails void onNotifyDeviceRemoved(QString strDevId); Q_SIGNALS: void clicked(); void convertShowWindow(QString strDriveId, QString strMountUri); void convertUpdateWindow(QString, unsigned); void unloadMount(); void telephoneMount(); bool deviceError(GDrive*); void mountVolume(GVolume*); void ejectVolumeForce(GVolume*); void remountVolume(FDVolumeInfo volumeInfo); void checkDriveValid(FDDriveInfo driveInfo); void notifyDeviceRemoved(QString strDevId); }; #endif ukui-panel-3.0.6.4/ukui-flash-disk/flashdiskdata.h0000644000175000017500000000672714203402514020336 0ustar fengfeng/* * Copyright (C) 2021 KylinSoft Co., Ltd. * * Authors: * Yang Min yangmin@kylinos.cn * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include #include #include #include #include using namespace std; typedef struct FDMountInfo_s { string strId = ""; string strName = ""; bool isCanUnmount = false; bool isCanEject = false; string strTooltip = ""; string strUri = ""; bool isNativeDev = false; bool isNewInsert = false; quint64 lluTotalSize = 0; quint64 lluMountTick = 0; string strIconPath = ""; }FDMountInfo; typedef struct FDVolumeInfo_s { string strId = ""; string strName = ""; string strDevName = ""; bool isCanMount = false; bool isShouldAutoMount = false; bool isCanEject = false; bool isNewInsert = false; FDMountInfo mountInfo; string strIconPath = ""; }FDVolumeInfo; Q_DECLARE_METATYPE(FDVolumeInfo); typedef struct FDDriveInfo_s { string strId = ""; string strName = ""; bool isCanEject = false; bool isRemovable = false; bool isCanStart = false; bool isCanStop = false; map listVolumes; string strIconPath = ""; }FDDriveInfo; class FlashDiskData : public QObject { Q_OBJECT public: virtual ~FlashDiskData(); static FlashDiskData* getInstance(); map& getDevInfoWithDrive(); map& getDevInfoWithVolume(); map& getDevInfoWithMount(); int addDriveInfo(FDDriveInfo driveInfo); int addVolumeInfoWithDrive(FDDriveInfo driveInfo, FDVolumeInfo volumeInfo); int addMountInfoWithDrive(FDDriveInfo driveInfo, FDVolumeInfo volumeInfo, FDMountInfo mountInfo); int addVolumeInfo(FDVolumeInfo volumeInfo); int addMountInfo(FDMountInfo mountInfo); int removeDriveInfo(FDDriveInfo driveInfo); int removeVolumeInfo(FDVolumeInfo volumeInfo); int removeMountInfo(FDMountInfo mountInfo); unsigned getValidInfoCount(); void clearAllData(); bool isMountInfoExist(FDMountInfo mountInfo); void resetAllNewState(); quint64 getMountTickDiff(FDMountInfo mountInfo); bool getVolumeInfoByMount(FDMountInfo mountInfo, FDVolumeInfo& volumeInfo); unsigned getAttachedVolumeCount(string strId); QString getVolumeIcon(QString strVolumeId); void OutputInfos(); Q_SIGNALS: void notifyDeviceRemoved(QString strDevId); private: FlashDiskData(); static FlashDiskData *m_instance; static QMutex m_mutex; map m_devInfoWithDrive; // map m_devInfoWithVolume; // except with drive map m_devInfoWithMount; // except with volume }; #endif // __FLASHDISKDATA_H__ ukui-panel-3.0.6.4/ukui-flash-disk/fdclickwidget.cpp0000644000175000017500000003572214203402514020667 0ustar fengfeng/* * Copyright (C) 2021 KylinSoft Co., Ltd. * * Authors: * Yang Min yangmin@kylinos.cn * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include "flashdiskdata.h" #include "UnionVariable.h" FDClickWidget::FDClickWidget(QWidget *parent, unsigned diskNo, QString strDriveId, QString strVolumeId, QString strMountId, QString driveName, QString volumeName, quint64 capacityDis, QString strMountUri) : QWidget(parent), m_uDiskNo(diskNo), m_driveName(driveName), m_volumeName(volumeName), m_capacityDis(capacityDis), m_mountUri(strMountUri), m_driveId(strDriveId), m_volumeId(strVolumeId), m_mountId(strMountId) { //union layout /* * it's the to set the title interface,we get the drive name and add picture of a u disk */ const QByteArray id(THEME_QT_SCHEMA); if(QGSettings::isSchemaInstalled(id)) { fontSettings = new QGSettings(id); } const QByteArray idd(THEME_QT_SCHEMA); if(QGSettings::isSchemaInstalled(idd)) { qtSettings = new QGSettings(idd); } initFontSize(); initThemeMode(); QHBoxLayout *drivename_H_BoxLayout = new QHBoxLayout(); if (m_uDiskNo <= 1) { image_show_label = new QLabel(this); image_show_label->setFocusPolicy(Qt::NoFocus); image_show_label->installEventFilter(this); //to get theme picture for label #if IFDISTINCT_DEVICON QString strDevId = m_driveId.isEmpty()?m_volumeId:m_driveId; QString strIcon = FlashDiskData::getInstance()->getVolumeIcon(strDevId); imgIcon = QIcon::fromTheme(strIcon); if (imgIcon.isNull()) { imgIcon = QIcon::fromTheme("drive-removable-media-usb"); } #else imgIcon = QIcon::fromTheme("drive-removable-media-usb"); #endif QPixmap pixmap = imgIcon.pixmap(QSize(24, 24)); image_show_label->setPixmap(pixmap); image_show_label->setFixedSize(30,30); m_driveName_label = new QLabel(this); m_driveName_label->setFont(QFont("Noto Sans CJK SC",fontSize)); QString DriveName = getElidedText(m_driveName_label->font(), m_driveName, 180); m_driveName_label->setText(DriveName); if (DriveName != m_driveName) { m_driveName_label->setToolTip(m_driveName); } m_driveName_label->setFixedWidth(180); m_driveName_label->setObjectName("driveNameLabel"); m_eject_button = new QPushButton(this); m_eject_button->setProperty("useIconHighlightEffect", 0x2); m_eject_button->setProperty("useButtonPalette", true); m_eject_button->setFlat(true); //this property set that when the mouse is hovering in the icon the icon will move up a litte m_eject_button->move(m_eject_button->x()+234,m_eject_button->y()); //m_eject_button->installEventFilter(this); m_eject_button->setIcon(QIcon::fromTheme("media-eject-symbolic")); m_eject_button->setFixedSize(36,36); m_eject_button->setToolTip(tr("Eject")); connect(m_eject_button,SIGNAL(clicked()),SLOT(switchWidgetClicked())); // this signal-slot function is to emit a signal which //is to trigger a slot in mainwindow drivename_H_BoxLayout->setContentsMargins(0,0,0,0); drivename_H_BoxLayout->addSpacing(8); drivename_H_BoxLayout->addWidget(image_show_label); drivename_H_BoxLayout->addWidget(m_driveName_label); drivename_H_BoxLayout->addStretch(); } QVBoxLayout *main_V_BoxLayout = new QVBoxLayout(this); main_V_BoxLayout->setContentsMargins(6, 0, 6, 0); //main_V_BoxLayout->setMargin(0); disWidgetNumOne = new QWidget(this); QHBoxLayout *onevolume_h_BoxLayout = new QHBoxLayout(); m_nameDis1_label = new ClickLabel(disWidgetNumOne); m_nameDis1_label->setFont(QFont("Microsoft YaHei",fontSize)); handleVolumeLabelForFat32Me(m_volumeName, m_volumeId); QString VolumeName = getElidedText(m_nameDis1_label->font(), m_volumeName, 120); m_nameDis1_label->adjustSize(); m_nameDis1_label->setText("- "+VolumeName+":"); if (m_volumeName != VolumeName) { m_nameDis1_label->setToolTip(m_volumeName); } m_capacityDis1_label = new QLabel(disWidgetNumOne); QString str_capacityDis1 = size_human(m_capacityDis); m_capacityDis1_label->setFont(QFont("Microsoft YaHei",fontSize)); m_capacityDis1_label->setText("("+str_capacityDis1+")"); m_capacityDis1_label->setObjectName("capacityLabel"); onevolume_h_BoxLayout->setSpacing(0); onevolume_h_BoxLayout->addSpacing(50); onevolume_h_BoxLayout->setMargin(0); //使得widget上的label得以居中显示 onevolume_h_BoxLayout->addWidget(m_nameDis1_label); onevolume_h_BoxLayout->addWidget(m_capacityDis1_label); onevolume_h_BoxLayout->addSpacing(10); onevolume_h_BoxLayout->addStretch(); disWidgetNumOne->setObjectName("OriginObjectOnly"); disWidgetNumOne->setLayout(onevolume_h_BoxLayout); disWidgetNumOne->installEventFilter(this); disWidgetNumOne->setFixedHeight(30); main_V_BoxLayout->addLayout(drivename_H_BoxLayout); if (m_mountUri.isEmpty()) { m_capacityDis1_label->setText(tr("Unmounted")); } main_V_BoxLayout->addWidget(disWidgetNumOne); this->setLayout(main_V_BoxLayout); if (m_uDiskNo <= 1) { this->setFixedSize(276,64); } else { this->setFixedSize(276,36); } this->setAttribute(Qt::WA_TranslucentBackground, true); // check capacity lable width m_strCapacityDis = m_capacityDis1_label->text(); int nNameWidth = m_nameDis1_label->fontMetrics().boundingRect(m_nameDis1_label->text()).width(); QString strCapacity = getElidedText(m_capacityDis1_label->font(), m_strCapacityDis, 210-nNameWidth); if (strCapacity != m_strCapacityDis) { m_capacityDis1_label->setText(strCapacity); m_capacityDis1_label->setToolTip(m_strCapacityDis); } connect(this, &FDClickWidget::themeFontChange, this, &FDClickWidget::onThemeFontChange); } void FDClickWidget::initFontSize() { if (!fontSettings) { fontSize = 11; return; } connect(fontSettings,&QGSettings::changed,[=](QString key) { if("systemFont" == key || "systemFontSize" == key) { fontSize = fontSettings->get(FONT_SIZE).toString().toFloat(); Q_EMIT themeFontChange(fontSize); } }); QStringList keys = fontSettings->keys(); if (keys.contains("systemFont") || keys.contains("systemFontSize")) { fontSize = fontSettings->get(FONT_SIZE).toInt(); } } void FDClickWidget::onThemeFontChange(qreal lfFontSize) { } void FDClickWidget::initThemeMode() { if(!qtSettings) { currentThemeMode = "ukui-white"; } QStringList keys = qtSettings->keys(); if(keys.contains("styleName")) { currentThemeMode = qtSettings->get("style-name").toString(); } } FDClickWidget::~FDClickWidget() { if(chooseDialog) delete chooseDialog; if(gpartedface) delete gpartedface; if (fontSettings) { delete fontSettings; fontSettings = nullptr; } if (qtSettings) { delete qtSettings; qtSettings = nullptr; } } void FDClickWidget::mousePressEvent(QMouseEvent *ev) { mousePos = QPoint(ev->x(), ev->y()); } void FDClickWidget::mouseReleaseEvent(QMouseEvent *ev) { if(mousePos == QPoint(ev->x(), ev->y())) Q_EMIT clicked(); } //click the first area to show the interface void FDClickWidget::on_volume_clicked() { if (!m_mountUri.isEmpty()) { QString aaa = "peony "+m_mountUri; QProcess::startDetached(aaa.toUtf8().data()); this->topLevelWidget()->hide(); } } void FDClickWidget::switchWidgetClicked() { EjectDeviceInfo eDeviceInfo; eDeviceInfo.strDriveId = m_driveId; eDeviceInfo.strDriveName = m_driveName; eDeviceInfo.strVolumeId = m_volumeId; eDeviceInfo.strVolumeName = m_volumeName; eDeviceInfo.strMountId = m_mountId; eDeviceInfo.strMountUri = m_mountUri; Q_EMIT clickedEject(eDeviceInfo); } QPixmap FDClickWidget::drawSymbolicColoredPixmap(const QPixmap &source) { if(currentThemeMode == "ukui-light" || currentThemeMode == "ukui-white") { QImage img = source.toImage(); for (int x = 0; x < img.width(); x++) { for (int y = 0; y < img.height(); y++) { auto color = img.pixelColor(x, y); if (color.alpha() > 0) { color.setRed(0); color.setGreen(0); color.setBlue(0); img.setPixelColor(x, y, color); } } } return QPixmap::fromImage(img); } else if(currentThemeMode == "ukui-dark" || currentThemeMode == "ukui-black" || currentThemeMode == "ukui-default" ) { QImage img = source.toImage(); for (int x = 0; x < img.width(); x++) { for (int y = 0; y < img.height(); y++) { auto color = img.pixelColor(x, y); if (color.alpha() > 0) { color.setRed(255); color.setGreen(255); color.setBlue(255); img.setPixelColor(x, y, color); } } } return QPixmap::fromImage(img); } else { QImage img = source.toImage(); for (int x = 0; x < img.width(); x++) { for (int y = 0; y < img.height(); y++) { auto color = img.pixelColor(x, y); if (color.alpha() > 0) { color.setRed(0); color.setGreen(0); color.setBlue(0); img.setPixelColor(x, y, color); } } } return QPixmap::fromImage(img); } } //to convert the capacity by another type QString FDClickWidget::size_human(qlonglong capacity) { // float capacity = this->size(); if(capacity > 1) { int conversionNum = 0; QStringList list; list << "KB" << "MB" << "GB" << "TB"; QStringListIterator i(list); QString unit("B"); qlonglong conversion = capacity; while(conversion >= 1024.0 && i.hasNext()) { unit = i.next(); conversion /= 1024.0; conversionNum++; } qlonglong remain = capacity - conversion * qPow(1024,conversionNum); double showRemain = 0.0; if(conversionNum == 4) { showRemain = (float)remain /1024/1024/1024/1024; } else if(conversionNum == 3) { showRemain = (float)remain /1024/1024/1024; } else if(conversionNum == 2) { showRemain = (float)remain /1024/1024; } else if(conversionNum == 1) { showRemain = (float)remain /1024; } double showValue = conversion + showRemain; QString str2=QString::number(showValue,'f',1); QString str_capacity=QString(" %1%2").arg(str2).arg(unit); return str_capacity; // return QString().setNum(capacity,'f',2)+" "+unit; } #if (QT_VERSION < QT_VERSION_CHECK(5,7,0)) if(capacity == NULL) { QString str_capaticity = tr("the capacity is empty"); return str_capaticity; } #endif if(capacity == 1) { QString str_capacity = tr("blank CD"); return str_capacity; } QString str_capacity = tr("other user device"); return str_capacity; } //set the style of the eject button and label when the mouse doing some different operations bool FDClickWidget::eventFilter(QObject *obj, QEvent *event) { if(obj == m_eject_button) { if(event->type() == QEvent::MouseButtonPress) { if(currentThemeMode == "ukui-dark" || currentThemeMode == "ukui-black" || currentThemeMode == "ukui-default") { m_eject_button->setIconSize(QSize(14,14)); m_eject_button->setFixedSize(38,38); } else { m_eject_button->setIconSize(QSize(14,14)); m_eject_button->setFixedSize(38,38); } } if(event->type() == QEvent::Enter) { if(currentThemeMode == "ukui-dark" || currentThemeMode == "ukui-black" || currentThemeMode == "ukui-default") { m_eject_button->setIconSize(QSize(16,16)); m_eject_button->setFixedSize(40,40); } else { m_eject_button->setIconSize(QSize(16,16)); m_eject_button->setFixedSize(40,40); } } if(event->type() == QEvent::Leave) { if(currentThemeMode == "ukui-dark" || currentThemeMode == "ukui-black") { m_eject_button->setIconSize(QSize(16,16)); m_eject_button->setFixedSize(40,40); } else { m_eject_button->setIconSize(QSize(16,16)); m_eject_button->setFixedSize(40,40); } } } if(obj == disWidgetNumOne) { if(event->type() == QEvent::Enter) { if(currentThemeMode == "ukui-dark" || currentThemeMode == "ukui-black" || currentThemeMode == "ukui-default" || currentThemeMode == "ukui") { disWidgetNumOne->setStyleSheet( "QWidget#OriginObjectOnly{background:rgba(255,255,255,0.12);" "border-radius: 6px;}"); } else { disWidgetNumOne->setStyleSheet( "QWidget#OriginObjectOnly{background:rgba(0,0,0,0.12);" "border-radius: 6px;}"); } } if(event->type() == QEvent::Leave) { disWidgetNumOne->setStyleSheet(""); } if(event->type() == QEvent::MouseButtonPress) { on_volume_clicked(); } } return false; } void FDClickWidget::resizeEvent(QResizeEvent *event) { } ukui-panel-3.0.6.4/ukui-flash-disk/ukui-flash-disk.qrc0000644000175000017500000000041214203402514021053 0ustar fengfeng ukui-flash-disk.qss picture/media-eject-symbolic.svg picture/drive-removable-media.svg picture/drive-removable-media-usb.png ukui-panel-3.0.6.4/ukui-flash-disk/datacdrom.cpp0000644000175000017500000004207714203402514020023 0ustar fengfeng/* * Peony-Qt's Library * * Copyright (C) 2020, KylinSoft Co., Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this library. If not, see . * * Authors: renpeijia * */ #include "datacdrom.h" #include #include #include #include #include #include #include #include #include #include DataCDROM::DataCDROM(QString &blockName, QObject *parent) : QObject(parent) { m_oBlockName = blockName; m_iHandle = -1; m_oMediumType.clear(); m_u32MediumRSupport = 0; m_u32MediumWSupport = 0; m_u32TrackNumber = 0; m_u64UsedCapacity = 0; m_u64FreeCapacity = 0; m_u64Capacity = 0; } DataCDROM::~DataCDROM() { } void DataCDROM::getCDROMInfo() { int ret = 0; // 0. open device. if (!open()) { qWarning()<<"open cdrom device failed"; return; } // 1. load support mediu types. ret = checkRWSupport(); if (ret < 0) { qWarning()<<"check support type failed"; close(); return; } // 2. check have medium or not. ret = checkMediumType(); if (ret < 0) { qWarning()<<"check medium type failed"; close(); return; } //3、get track num ret = cdRomGetTrackNum(); if (ret < 0) { qWarning()<<"get cdrom track num failed"; close(); return; } //4、get capacity cdRomCapacity(); //5、close device close(); return; } bool DataCDROM::open() { if (-1 != m_iHandle) { return true; } m_iHandle = ::open(m_oBlockName.toUtf8().constData(), O_NONBLOCK | O_RDONLY); if (m_iHandle < 0) { qWarning()<> 8); cdb[8] = (len & 0x00FF); // get real result. if (!execSCSI(cdb, 12, result, len)) { qWarning()<<"scsi get medium read type support"; return -1; } len = result[11]; // loop result, adjust support read medium type. for (int i = 0; i < len; ++i) { switch ((result[i + 12] << 8) | result[i + 13]) { case 0x0008: // CD-ROM m_u32MediumRSupport |= MEDIUM_CD_ROM; break; case 0x0009: // CD-R m_u32MediumRSupport |= MEDIUM_CD_R; break; case 0x000A: // CD-RW m_u32MediumRSupport |= MEDIUM_CD_RW; break; // 000B - 000F reserved. case 0x0010: // DVD-ROM m_u32MediumRSupport |= MEDIUM_DVD_ROM; break; case 0x0011: // DVD-R m_u32MediumRSupport |= MEDIUM_DVD_R; break; case 0x0012: // DVD-RAM m_u32MediumRSupport |= MEDIUM_DVD_RAM; break; // define in MMC-5 case 0x0013: // DVD-RW m_u32MediumRSupport |= MEDIUM_DVD_RW_OVERWRITE; break; case 0x0014: m_u32MediumRSupport |= MEDIUM_DVD_RW_SEQ; break; case 0x0015: m_u32MediumRSupport |= MEDIUM_DVD_R_DL_SEQ; break; case 0x0016: m_u32MediumRSupport |= MEDIUM_DVD_R_DL_JUMP; break; case 0x001A: // DVD+RW m_u32MediumRSupport |= MEDIUM_DVD_PLUS_RW; break; case 0x001B: //DVD+R m_u32MediumRSupport |= MEDIUM_DVD_PLUS_R; break; case 0x002B: m_u32MediumRSupport |= MEDIUM_DVD_PLUS_R_DL; break; case 0x0002: // qDebug()<< "Removable CDROM."; break; default: // qDebug()<<"Unkown medium type" << ((result[i + 12] << 8) | result[i + 13]); break; } } // load write suppport // CD TAO cdb[2] = 0x00; cdb[3] = 0x2D; cdb[7] = 0x00; cdb[8] = 0x10; if (!execSCSI(cdb, 12, result, 16)) { qWarning()<<"scsi get cd tao write support failed."; return -1; } if (result[8] == cdb[2] && result[9] == cdb[3]) { m_u32MediumWSupport |= MEDIUM_CD_R; if (result[12] & 0x02) { m_u32MediumWSupport |= MEDIUM_CD_RW; } } //CD SAO cdb[2] = 0x00; cdb[3] = 0x2E; cdb[7] = 0x00; cdb[8] = 0x10; if (!execSCSI(cdb, 12, result, 16)) { qWarning()<<"scsi get cd sao write medium support failed"; return -1; } if (result[8] == cdb[2] && result[9] == cdb[3]){ m_u32MediumWSupport |= MEDIUM_CD_R; if (result[12] & 0x02) { m_u32MediumWSupport |= MEDIUM_CD_RW; } } //DVD cdb[2] = 0x00; cdb[3] = 0x1F; cdb[7] = 0x00; cdb[8] = 0x10; if (!execSCSI(cdb, 12, result, 16)) { qWarning()<<"scsi get DVD-ROM read medium support failed"; return -1; } if (result[8] == cdb[2] && result[9] == cdb[3]) { m_u32MediumRSupport |= MEDIUM_DVD_ROM; //qDebug("%1 sure support read mode : DVD-ROM"); } //DVD+RW cdb[2] = 0x00; cdb[3] = 0x2A; cdb[7] = 0x00; cdb[8] = 0x10; if (!execSCSI(cdb, 12, result, 16)) { qWarning()<<"scsi get DVD+RW write medium support failed"; return -1; } if (result[8] == cdb[2] && result[9] == cdb[3]){ if (result[12] & 0x01) { m_u32MediumWSupport |= MEDIUM_DVD_PLUS_RW; } else { m_u32MediumWSupport |= MEDIUM_DVD_ROM; } } //DVD+R cdb[2] = 0x00; cdb[3] = 0x2B; cdb[7] = 0x00; cdb[8] = 0x10; if (!execSCSI(cdb, 12, result, 16)) { qWarning()<<"scsi get DVD+R RW medium support failed"; return -1; } if (result[8] == cdb[2] && result[9] == cdb[3]) { m_u32MediumRSupport |= MEDIUM_DVD_PLUS_R; if (result[12] & 0x01) { m_u32MediumWSupport |= MEDIUM_DVD_PLUS_R; } } //DVD-R / DVD-RW cdb[2] = 0x00; cdb[3] = 0x2F; cdb[7] = 0x00; cdb[8] = 0x10; if (!execSCSI(cdb, 12, result, 16)) { qWarning()<<"scsi get DVD-R/DVD-RW RW medium type support failed"; return -1; } if (result[8] == cdb[2] && result[9] == cdb[3]) { m_u32MediumRSupport |= MEDIUM_DVD_R; //qDebug("it sure support read mode : DVD-R"); m_u32MediumWSupport |= MEDIUM_DVD_R; //qDebug("it support write mode : DVD-R"); m_u32MediumRSupport |= MEDIUM_DVD_RW; //qDebug("it sure support read mode : DVD-RW"); if (result[12] & 0x02) { m_u32MediumWSupport |= MEDIUM_DVD_RW; //qDebug("%1 support write mode : DVD-RW"); } } if (m_u32MediumRSupport & ((MEDIUM_DVD_RW_OVERWRITE | MEDIUM_DVD_RW_SEQ))) { m_u32MediumRSupport |= MEDIUM_DVD_RW; } qDebug()<<"m_u32MediumRSupport"< 0; --index){ if (dvdInfo.at(index).startsWith("READ FORMAT CAPACITIES:")) { QStringList formatCapacity = dvdInfo.takeAt(index + 1).split("="); qWarning()<<"format capacity is"<> 24); cdb[3] = (m_u32TrackNumber >> 16); cdb[4] = (m_u32TrackNumber >> 8); cdb[5] = m_u32TrackNumber; if (!execSCSI(cdb, 10, result, 40)) { qWarning()<<"scsi get cd rom capacity failed."; return; } m_u64UsedCapacity = ((result[8] << 24) | (result[9] << 16) | (result[10] << 8) | result[11]); m_u64UsedCapacity *= 2048; m_u64FreeCapacity = ((result[16] << 24) | (result[17] << 16) | (result[18] << 8) | result[19]); m_u64FreeCapacity *= 2048; m_u64Capacity = m_u64UsedCapacity + m_u64FreeCapacity; qDebug()<<"total capacity:"< #include #include class DeviceManager : public QObject { Q_OBJECT public: static const DeviceManager* getInstance(); private: explicit DeviceManager(QObject* parent = nullptr); ~DeviceManager(); static void drive_connected_callback(GVolumeMonitor* monitor, GDrive* drive, gpointer pThis); static void drive_disconnected_callback(GVolumeMonitor* monitor, GDrive* drive, gpointer pThis); Q_SIGNALS: void driveDisconnected(QString drive); private: static DeviceManager* gInstance; GVolumeMonitor* mGvolumeMonitor = nullptr; QMap mDevice; }; #endif // DEVICEMANAGER_H ukui-panel-3.0.6.4/ukui-flash-disk/disk-resources/0000755000175000017500000000000014203402514020311 5ustar fengfengukui-panel-3.0.6.4/ukui-flash-disk/disk-resources/ukui-flash-disk.desktop0000644000175000017500000000036114203402514024704 0ustar fengfeng[Desktop Entry] Name=ukui flash disk Name[zh_CN]=U盘管理工具 Comment=Ukui Flash Disk Comment[zh_CN]=u盘管理工具 Exec=ukui-flash-disk Terminal=false Type=Application Icon=panel X-UKUI-AutoRestart=true OnlyShowIn=UKUI NoDisplay=true ukui-panel-3.0.6.4/ukui-flash-disk/disk-resources/ukui-flash-disk_tr.qm0000644000175000017500000000052214203402514024354 0ustar fengfeng true auto load udisk Control if auto load udisk ukui-panel-3.0.6.4/ukui-flash-disk/disk-resources/ukui-flash-disk_zh_CN.ts0000644000175000017500000002743214203402514024752 0ustar fengfeng BaseDialog Disk test 设备检测 DeviceOperation unknown 未知 FDClickWidget the capacity is empty 容量为空 blank CD 空光盘 other user device 其它用户设备 another device 其它设备 Eject 弹出 Unmounted 未装载 FormateDialog Formatted successfully! 格式化成功 Formatting failed, please unplug the U disk and try again! 格式化失败,请拔出设备并重试! Format 格式化 Rom size: 容量: Filesystem: 文件系统: Disk name: 分区名: Completely erase(Time is longer, please confirm!) 完全擦除(耗时长,请确认!) Cancel 取消 Format disk 格式化 Formatting this volume will erase all data on it. Please back up all retained data before formatting. Do you want to continue? 格式化将清除卷上所有数据,请在格式化操作前备份好数据。确定继续格式化? Disk test U盘检测 Disk format 设备格式化 MainWindow usb management tool U盘管理工具 ukui-flash-disk U盘管理工具 kindly reminder 温馨提示 wrong reminder 错误提示 Please do not pull out the USB flash disk when reading or writing 设备读写时请不要直接拔出 Please do not pull out the CDROM when reading or writing 光盘读写时请不要直接拔出 Please do not pull out the SD Card when reading or writing SD卡读写时请不要直接拔出 There is a problem with this device 此设备存在问题 telephone device 手机设备 Removable storage device removed 移动存储设备已移除 Please do not pull out the storage device when reading or writing 存储设备读写时请不要直接拔出 Storage device removed 存储设备已移除 MainWindow ukui flash disk U盘管理工具 MessageBox OK 确认 Cancel 取消 Format 格式化 QClickWidget the capacity is empty 容量为空 blank CD 空光盘 other user device 其它用户设备 another device 其它设备 Unmounted 未装载 弹出 RepairDialogBox Disk test 设备检测 <h4>The system could not recognize the disk contents</h4><p>Check that the disk and drive are properly connected, make sure the disk is not a read-only disk, and try again. For more information, search for help on read-only files and how to change read-only files.</p> <h4>系统无法识别U盘内容</h4><p>检查磁盘和驱动器是否正确连接,确保磁盘不是只读磁盘,然后重试。有关更多信息,请搜索有关只读文件和如何更改只读文件的帮助。</p> Format disk 格式化设备 Repair 修复 <h4>The system could not recognize the disk contents</h4><p>Check that the disk/drive is properly connected,make sure the disk is not a read-only disk, and try again.For more information, search for help on read-only files andhow to change read-only files.</p> <h4>系统无法识别移动设备内容</h4><p>检查磁盘/驱动器是否正确连接,确保磁盘不是只读磁盘,然后重试。有关更多信息,请搜索有关只读文件和如何更改只读文件的帮助。</p> <h4>The system could not recognize the disk contents</h4><p>Check that the disk/drive '%1' is properly connected,make sure the disk is not a read-only disk, and try again.For more information, search for help on read-only files andhow to change read-only files.</p> <h4>系统无法识别移动设备内容</h4><p>检查磁盘/驱动器 "%1" 是否正确连接,确保磁盘不是只读磁盘,然后重试。有关更多信息,请搜索有关只读文件和如何更改只读文件的帮助。</p> RepairProgressBar <h3>%1</h3> <h3>%1</h3> Attempting a disk repair... 正在尝试修复设备... Cancel 取消 Repair successfully! 修复成功! The repair completed. If the USB flash disk is not mounted, please try formatting the device! 修复失败,如果设备没有成功挂载,请尝试格式化修复! Disk test U盘检测 Disk repair 设备检测 Repair failed. If the USB flash disk is not mounted, please try formatting the device! 修复失败,如果设备没有成功挂载,请尝试格式化修复! ejectInterface usb has been unplugged safely U盘已安全拔出 cdrom has been unplugged safely 光盘已安全拔出 sd has been unplugged safely SD卡已安全拔出 usb is occupying unejectable U盘占用无法弹出 Storage device can be safely unplugged 存储设备可以安全拔出 gpartedInterface ok 确定 interactiveDialog usb is occupying,do you want to eject it U盘正在占用中,你想弹出它吗 cdrom is occupying,do you want to eject it 光盘正在占用中,你想弹出它吗 sd is occupying,do you want to eject it SD卡正在占用中,你想弹出它吗 cancle 取消 yes 确定 cdrom is occupying 光盘正在占用中 sd is occupying SD卡正在占用中 usb is occupying U盘正在占用中 ukui-panel-3.0.6.4/ukui-flash-disk/disk-resources/ukui-flash-disk.pro0000644000175000017500000000370614203402514024041 0ustar fengfengQT += core gui KWindowSystem dbus network greaterThan(QT_MAJOR_VERSION, 4): QT += widgets TARGET = ukui-flash-disk TEMPLATE = app PKGCONFIG += gio-2.0 gsettings-qt udisks2 #LIBS +=-lgio-2.0 -lglib-2.0 CONFIG += c++11 link_pkgconfig no_keywords debug DEFINES += QT_DEPRECATED_WARNINGS #include($$PWD/../QtSingleApplication/qtsinglecoreapplication.pri) SOURCES += \ $$PWD/../main.cpp \ $$PWD/../mainwindow.cpp \ $$PWD/../MainController.cpp \ $$PWD/../device-manager.cpp \ $$PWD/../device-operation.cpp \ $$PWD/../repair-dialog-box.cpp \ $$PWD/../UnionVariable.cpp \ $$PWD/../qclickwidget.cpp \ $$PWD/../fdapplication.cpp \ $$PWD/../clickLabel.cpp \ $$PWD/../fdframe.cpp \ $$PWD/../flashdiskdata.cpp \ $$PWD/../fdclickwidget.cpp \ $$PWD/../interactivedialog.cpp \ $$PWD/../ejectInterface.cpp \ $$PWD/../datacdrom.cpp \ $$PWD/../QtSingleApplication/qtsingleapplication.cpp \ $$PWD/../QtSingleApplication/qtlocalpeer.cpp \ # Removablemount.cpp HEADERS += \ $$PWD/../device-manager.h \ $$PWD/../device-operation.h \ $$PWD/../repair-dialog-box.h \ $$PWD/../UnionVariable.h \ $$PWD/../mainwindow.h \ $$PWD/../MainController.h \ $$PWD/../clickLabel.h \ $$PWD/../qclickwidget.h \ $$PWD/../fdapplication.h \ $$PWD/../fdframe.h \ $$PWD/../flashdiskdata.h \ $$PWD/../fdclickwidget.h \ $$PWD/../interactivedialog.h \ $$PWD/../ejectInterface.h \ $$PWD/../datacdrom.h \ $$PWD/../QtSingleApplication/qtsingleapplication.h \ $$PWD/../QtSingleApplication/qtlocalpeer.h \ $$PWD/../QtSingleApplication/qtlocalpeer.h \ # Removablemount.h FORMS += \ $$PWD/../mainwindow.ui TRANSLATIONS += \ ukui-flash-disk_tr.ts \ ukui-flash-disk_zh_CN.ts ukui-panel-3.0.6.4/ukui-flash-disk/disk-resources/ukui-flash-disk_zh_CN.qm0000644000175000017500000001220314203402514024727 0ustar fengfeng|~elՋR+yRYQ[</h4><p>hgxv/qRVh "%1" f/T&kcxnc xnOxvN f/Sxv q6T͋0g QsfYO`o d}"g QsSeNTYOUfe9SeNv^.R0</p>

The system could not recognize the disk contents

Check that the disk/drive '%1' is properly connected,make sure the disk is not a read-only disk, and try again.For more information, search for help on read-only files andhow to change read-only files.

RepairDialogBox<h4>|~elՋR+yRYQ[</h4><p>hgxv/qRVhf/T&kcxnc xnOxvN f/Sxv q6T͋0g QsfYO`o d}"g QsSeNTYOUfe9SeNv^.R0</p>

The system could not recognize the disk contents

Check that the disk/drive is properly connected,make sure the disk is not a read-only disk, and try again.For more information, search for help on read-only files andhow to change read-only files.

RepairDialogBoxYhmK Disk testRepairDialogBox h<_SY Format diskRepairDialogBoxOY RepairRepairDialogBox<h3>%1</h3>

%1

RepairProgressBarkcW(\OY Y...Attempting a disk repair...RepairProgressBarSmCancelRepairProgressBarYhmK Disk repairRepairProgressBar2OY Y1% YgYlg bRc} \h<_SOY VRepair failed. If the USB flash disk is not mounted, please try formatting the device!RepairProgressBar OY bRRepair successfully!RepairProgressBar[XPYSN[QhbQ&Storage device can be safely unpluggedejectInterfaceSmcancleinteractiveDialogQIvkcW(S`u(N-cdrom is occupyinginteractiveDialogQIvkcW(S`u(N- O``_9Q[T*cdrom is occupying,do you want to eject itinteractiveDialogSDSakcW(S`u(N-sd is occupyinginteractiveDialogSDSakcW(S`u(N- O``_9Q[T'sd is occupying,do you want to eject itinteractiveDialogUvkcW(S`u(N-usb is occupyinginteractiveDialogUvkcW(S`u(N- O``_9Q[T(usb is occupying,do you want to eject itinteractiveDialogxn[yesinteractiveDialogukui-panel-3.0.6.4/ukui-flash-disk/disk-resources/ukui-flash-disk_tr.ts0000644000175000017500000002176214203402514024376 0ustar fengfeng BaseDialog Disk test DeviceOperation unknown FDClickWidget the capacity is empty Kapasite boş blank CD blank CD other user device other user device another device another device Eject Çıkar Unmounted Unmounted FormateDialog Formatted successfully! Formatting failed, please unplug the U disk and try again! Format Rom size: Filesystem: Disk name: Completely erase(Time is longer, please confirm!) Cancel Format disk Formatting this volume will erase all data on it. Please back up all retained data before formatting. Do you want to continue? Disk format MainWindow usb management tool Usb yönetim aracı kindly reminder wrong reminder Please do not pull out the CDROM when reading or writing Please do not pull out the SD Card when reading or writing Please do not pull out the USB flash disk when reading or writing telephone device Please do not pull out the storage device when reading or writing Storage device removed MainWindow ukui flash disk MessageBox OK Cancel Format QClickWidget eject Çıkar the capacity is empty Kapasite boş Unmounted Unmounted blank CD blank CD other user device other user device 弹出 RepairDialogBox Disk test Format disk Repair <h4>The system could not recognize the disk contents</h4><p>Check that the disk/drive is properly connected,make sure the disk is not a read-only disk, and try again.For more information, search for help on read-only files andhow to change read-only files.</p> <h4>The system could not recognize the disk contents</h4><p>Check that the disk/drive '%1' is properly connected,make sure the disk is not a read-only disk, and try again.For more information, search for help on read-only files andhow to change read-only files.</p> RepairProgressBar <h3>%1</h3> Attempting a disk repair... Cancel Repair successfully! Disk repair Repair failed. If the USB flash disk is not mounted, please try formatting the device! ejectInterface usb has been unplugged safely USB güvenli bir şekilde çıkarıldı Storage device can be safely unplugged interactiveDialog cdrom is occupying,do you want to eject it sd is occupying,do you want to eject it usb is occupying,do you want to eject it cancle yes cdrom is occupying sd is occupying usb is occupying ukui-panel-3.0.6.4/ukui-flash-disk/ui_mainwindow.h0000644000175000017500000000415414204636772020415 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include "fdframe.h" QT_BEGIN_NAMESPACE class Ui_MainWindow { public: FDFrame *centralWidget; void setupUi(QMainWindow *MainWindow) { if (MainWindow->objectName().isEmpty()) MainWindow->setObjectName(QString::fromUtf8("MainWindow")); MainWindow->resize(400, 300); centralWidget = new FDFrame(MainWindow); centralWidget->setObjectName(QString::fromUtf8("centralWidget")); MainWindow->setCentralWidget(centralWidget); retranslateUi(MainWindow); QMetaObject::connectSlotsByName(MainWindow); } // setupUi void retranslateUi(QMainWindow *MainWindow) { MainWindow->setWindowTitle(QApplication::translate("MainWindow", "MainWindow", nullptr)); } // retranslateUi }; namespace Ui { class MainWindow: public Ui_MainWindow {}; } // namespace Ui QT_END_NAMESPACE #endif // UI_MAINWINDOW_H ukui-panel-3.0.6.4/ukui-flash-disk/qclickwidget.cpp0000644000175000017500000010647614203402514020543 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include void frobnitz_force_result_func(GDrive *source_object,GAsyncResult *res,QClickWidget *p_this) { auto env = qgetenv("QT_QPA_PLATFORMTHEME"); qDebug()<<"env"<removeOne(source_object); p_this->m_eject = new ejectInterface(p_this,g_drive_get_name(source_object),NORMALDEVICE,""); p_this->m_eject->show(); } else { int volumeNum = g_list_length(g_drive_get_volumes(source_object)); for(int eachVolume = 0 ; eachVolume < volumeNum ;eachVolume++) { p_this->flagType = 0; if(g_mount_can_unmount(g_volume_get_mount((GVolume *)g_list_nth_data(g_drive_get_volumes(source_object),eachVolume)))) { QtConcurrent::run([=](){ char *dataPath = g_file_get_path(g_mount_get_root(g_volume_get_mount((GVolume *)g_list_nth_data(g_drive_get_volumes(source_object),eachVolume)))); qDebug()<<"dataPath"<ifSucess = p.waitForFinished(); }); } } } } void frobnitz_result_func(GDrive *source_object,GAsyncResult *res,QClickWidget *p_this) { gboolean success = FALSE; GError *err = nullptr; success = g_drive_eject_with_operation_finish (source_object, res, &err); if (!err) { findGDriveList()->removeOne(source_object); p_this->m_eject = new ejectInterface(p_this,g_drive_get_name(source_object),NORMALDEVICE,""); p_this->m_eject->show(); } else /*if(g_drive_can_stop(source_object) == true)*/ { if (p_this->chooseDialog == nullptr) { p_this->chooseDialog = new interactiveDialog("", p_this); } // p_this->chooseDialog->raise(); p_this->chooseDialog->show(); p_this->chooseDialog->setFocus(); p_this->connect(p_this->chooseDialog,&interactiveDialog::FORCESIG,p_this,[=]() { g_drive_eject_with_operation(source_object, G_MOUNT_UNMOUNT_FORCE, NULL, NULL, GAsyncReadyCallback(frobnitz_force_result_func), p_this ); p_this->chooseDialog->close(); }); } } void frobnitz_force_result_tele(GVolume *source_object,GAsyncResult *res,QClickWidget *p_this) { gboolean success = FALSE; GError *err = nullptr; success = g_mount_unmount_with_operation_finish(g_volume_get_mount(source_object),res, &err); if(!err) { qDebug()<<"unload successful"; findTeleGVolumeList()->removeOne(source_object); findGVolumeList()->removeOne(source_object); if(findTeleGVolumeList()->size() == 1) { if(findGVolumeList()->size() == 1) { Q_EMIT p_this->noDeviceSig(); } } } } QClickWidget::QClickWidget(QWidget *parent, int num, GDrive *Drive, GVolume *Volume, QString driveName, QString nameDis1, QString nameDis2, QString nameDis3, QString nameDis4, qlonglong capacityDis1, qlonglong capacityDis2, qlonglong capacityDis3, qlonglong capacityDis4, QString pathDis1, QString pathDis2, QString pathDis3, QString pathDis4) : QWidget(parent), m_Num(num), m_Drive(Drive), m_driveName(driveName), m_nameDis1(nameDis1), m_nameDis2(nameDis2), m_nameDis3(nameDis3), m_nameDis4(nameDis4), m_capacityDis1(capacityDis1), m_capacityDis2(capacityDis2), m_capacityDis3(capacityDis3), m_capacityDis4(capacityDis4), m_pathDis1(pathDis1), m_pathDis2(pathDis2), m_pathDis3(pathDis3), m_pathDis4(pathDis4) { //union layout /* * it's the to set the title interface,we get the drive name and add picture of a u disk */ const QByteArray id(THEME_QT_SCHEMA); if(QGSettings::isSchemaInstalled(id)) { fontSettings = new QGSettings(id); } const QByteArray idd(THEME_QT_SCHEMA); if(QGSettings::isSchemaInstalled(idd)) { qtSettings = new QGSettings(idd); } initFontSize(); initThemeMode(); QHBoxLayout *drivename_H_BoxLayout = new QHBoxLayout(); drivename_H_BoxLayout = new QHBoxLayout(); image_show_label = new QLabel(this); image_show_label->setFocusPolicy(Qt::NoFocus); image_show_label->installEventFilter(this); //to get theme picture for label imgIcon = QIcon::fromTheme("drive-removable-media-usb"); QPixmap pixmap = imgIcon.pixmap(QSize(25, 25)); image_show_label->setPixmap(pixmap); image_show_label->setFixedSize(40,40); m_driveName_label = new QLabel(this); m_driveName_label->setFont(QFont("Noto Sans CJK SC",fontSize)); QString DriveName = getElidedText(m_driveName_label->font(), m_driveName, 180); m_driveName_label->setText(DriveName); m_driveName_label->setFixedSize(180,40); m_driveName_label->setObjectName("driveNameLabel"); m_eject_button = new QPushButton(this); m_eject_button->setFlat(true); //this property set that when the mouse is hovering in the icon the icon will move up a litte m_eject_button->move(m_eject_button->x()+234,m_eject_button->y()+2); //->setObjectName("Button"); m_eject_button->installEventFilter(this); m_eject_button->setIcon(drawSymbolicColoredPixmap(QPixmap::fromImage(QIcon::fromTheme("media-eject-symbolic").pixmap(24,24).toImage()))); m_eject_button->setFixedSize(40,40); m_eject_button->setToolTip(tr("弹出")); drivename_H_BoxLayout->addSpacing(8); drivename_H_BoxLayout->addWidget(image_show_label); drivename_H_BoxLayout->addWidget(m_driveName_label); drivename_H_BoxLayout->addStretch(); QVBoxLayout *main_V_BoxLayout = new QVBoxLayout(this); main_V_BoxLayout->setContentsMargins(0,0,0,0); connect(m_eject_button,SIGNAL(clicked()),SLOT(switchWidgetClicked())); // this signal-slot function is to emit a signal which //is to trigger a slot in mainwindow connect(m_eject_button, &QPushButton::clicked,this,[=]() { if(Drive != NULL) { g_drive_eject_with_operation(Drive, G_MOUNT_UNMOUNT_NONE, NULL, NULL, GAsyncReadyCallback(frobnitz_result_func), this); } else { g_mount_unmount_with_operation(g_volume_get_mount(Volume), G_MOUNT_UNMOUNT_NONE, NULL, NULL, GAsyncReadyCallback(frobnitz_force_result_tele), this); } }); //when the drive only has one vlolume //we set the information and set all details of the U disk in main interface if(m_Num == 1) { disWidgetNumOne = new QWidget(this); QHBoxLayout *onevolume_h_BoxLayout = new QHBoxLayout(); m_nameDis1_label = new ClickLabel(disWidgetNumOne); m_nameDis1_label->setFont(QFont("Microsoft YaHei",fontSize)); QString VolumeName = getElidedText(m_nameDis1_label->font(), m_nameDis1, 120); m_nameDis1_label->adjustSize(); m_nameDis1_label->setText("- "+VolumeName+":"); m_capacityDis1_label = new QLabel(disWidgetNumOne); QString str_capacityDis1 = size_human(m_capacityDis1); // QString str_capacityDis1Show = getElidedText(m_capacityDis1_label->font(),str_capacityDis1,200); m_capacityDis1_label->setFont(QFont("Microsoft YaHei",fontSize)); m_capacityDis1_label->setText("("+str_capacityDis1+")"); m_capacityDis1_label->setObjectName("capacityLabel"); onevolume_h_BoxLayout->setSpacing(0); onevolume_h_BoxLayout->addSpacing(50); onevolume_h_BoxLayout->setMargin(0); //使得widget上的label得以居中显示 onevolume_h_BoxLayout->addWidget(m_nameDis1_label); onevolume_h_BoxLayout->addWidget(m_capacityDis1_label); onevolume_h_BoxLayout->addSpacing(10); onevolume_h_BoxLayout->addStretch(); disWidgetNumOne->setObjectName("OriginObjectOnly"); disWidgetNumOne->setLayout(onevolume_h_BoxLayout); disWidgetNumOne->installEventFilter(this); disWidgetNumOne->setFixedHeight(30); main_V_BoxLayout->addLayout(drivename_H_BoxLayout); if (m_pathDis1.isEmpty()) { m_capacityDis1_label->setText(tr("Unmounted")); } main_V_BoxLayout->addWidget(disWidgetNumOne); this->setLayout(main_V_BoxLayout); this->setFixedSize(276,68); } //when the drive has two volumes if(m_Num == 2) { QHBoxLayout *onevolume_h_BoxLayout = new QHBoxLayout(); m_nameDis1_label = new ClickLabel(); m_nameDis1_label->setFont(QFont("Microsoft YaHei",fontSize)); QString VolumeNameDis1 = getElidedText(m_nameDis1_label->font(), m_nameDis1, 120); m_nameDis1_label->adjustSize(); m_nameDis1_label->setText("- "+VolumeNameDis1+":"); m_nameDis1_label->installEventFilter(this); m_capacityDis1_label = new QLabel(this); QString str_capacityDis1 = size_human(m_capacityDis1); m_capacityDis1_label->setFont(QFont("Microsoft YaHei",fontSize)); m_capacityDis1_label->setText("("+str_capacityDis1+")"); m_capacityDis1_label->setObjectName("capacityLabel"); onevolume_h_BoxLayout->addSpacing(50); onevolume_h_BoxLayout->setSpacing(0); onevolume_h_BoxLayout->addWidget(m_nameDis1_label); onevolume_h_BoxLayout->setMargin(0); onevolume_h_BoxLayout->addWidget(m_capacityDis1_label); onevolume_h_BoxLayout->addStretch(); disWidgetNumOne = new QWidget; disWidgetNumOne->setFixedHeight(30); disWidgetNumOne->setObjectName("OriginObjectOnly"); disWidgetNumOne->setLayout(onevolume_h_BoxLayout); disWidgetNumOne->installEventFilter(this); QHBoxLayout *twovolume_h_BoxLayout = new QHBoxLayout(); m_nameDis2_label = new ClickLabel(this); m_nameDis2_label->setFont(QFont("Microsoft YaHei",fontSize)); QString VolumeNameDis2 = getElidedText(m_nameDis2_label->font(), m_nameDis2, 120); m_nameDis2_label->setText("- "+VolumeNameDis2+":"); m_nameDis2_label->adjustSize(); m_nameDis2_label->installEventFilter(this); m_capacityDis2_label = new QLabel(this); QString str_capacityDis2 = size_human(m_capacityDis2); m_capacityDis2_label->setText("("+str_capacityDis2+")"); m_capacityDis2_label->setFont(QFont("Microsoft YaHei",fontSize)); m_capacityDis2_label->setObjectName("capacityLabel"); twovolume_h_BoxLayout->addSpacing(50); twovolume_h_BoxLayout->setSpacing(0); twovolume_h_BoxLayout->addWidget(m_nameDis2_label); twovolume_h_BoxLayout->setMargin(0); twovolume_h_BoxLayout->addWidget(m_capacityDis2_label); twovolume_h_BoxLayout->addStretch(); disWidgetNumTwo = new QWidget; disWidgetNumTwo->setFixedHeight(30); disWidgetNumTwo->setObjectName("OriginObjectOnly"); disWidgetNumTwo->setLayout(twovolume_h_BoxLayout); disWidgetNumTwo->installEventFilter(this); main_V_BoxLayout->setContentsMargins(0,0,0,0); main_V_BoxLayout->addLayout(drivename_H_BoxLayout); if(m_pathDis1 != "") { main_V_BoxLayout->addWidget(disWidgetNumOne); } if(m_pathDis2 != "") { main_V_BoxLayout->addWidget(disWidgetNumTwo); } main_V_BoxLayout->addStretch(); this->setLayout(main_V_BoxLayout); this->setFixedSize(276,97); } //when the drive has three volumes if(m_Num == 3) { QHBoxLayout *onevolume_h_BoxLayout = new QHBoxLayout(); m_nameDis1_label = new ClickLabel(this); m_nameDis1_label->setFont(QFont("Microsoft YaHei",fontSize)); QString VolumeNameDis1 = getElidedText(m_nameDis1_label->font(), m_nameDis2, 120); m_nameDis1_label->setText("- "+VolumeNameDis1+":"); m_nameDis1_label->adjustSize(); m_nameDis1_label->installEventFilter(this); //m_nameDis1_label->setText("- "+m_nameDis1+":"); m_capacityDis1_label = new QLabel(this); QString str_capacityDis1 = size_human(m_capacityDis1); m_capacityDis1_label->setFont(QFont("Microsoft YaHei",fontSize)); m_capacityDis1_label->setText("("+str_capacityDis1+")"); m_capacityDis1_label->setObjectName("capacityLabel"); onevolume_h_BoxLayout->addSpacing(50); onevolume_h_BoxLayout->setSpacing(0); onevolume_h_BoxLayout->addWidget(m_nameDis1_label); onevolume_h_BoxLayout->addWidget(m_capacityDis1_label); onevolume_h_BoxLayout->addStretch(); onevolume_h_BoxLayout->setMargin(0); disWidgetNumOne = new QWidget; disWidgetNumOne->setFixedHeight(30); disWidgetNumOne->setLayout(onevolume_h_BoxLayout); disWidgetNumOne->setObjectName("OriginObjectOnly"); disWidgetNumOne->installEventFilter(this); QHBoxLayout *twovolume_h_BoxLayout = new QHBoxLayout(); m_nameDis2_label = new ClickLabel(this); m_nameDis2_label->setFont(QFont("Microsoft YaHei",fontSize)); QString VolumeNameDis2 = getElidedText(m_nameDis2_label->font(), m_nameDis2, 120); m_nameDis2_label->setText("- "+VolumeNameDis2+":"); m_nameDis2_label->adjustSize(); m_nameDis2_label->installEventFilter(this); m_capacityDis2_label = new QLabel(this); QString str_capacityDis2 = size_human(m_capacityDis2); m_capacityDis2_label->setText("("+str_capacityDis2+")"); m_capacityDis2_label->setFont(QFont("Microsoft YaHei",fontSize)); m_capacityDis2_label->setObjectName("capacityLabel"); twovolume_h_BoxLayout->addSpacing(50); twovolume_h_BoxLayout->setSpacing(0); twovolume_h_BoxLayout->addWidget(m_nameDis2_label); twovolume_h_BoxLayout->addWidget(m_capacityDis2_label); twovolume_h_BoxLayout->addStretch(); twovolume_h_BoxLayout->setMargin(0); disWidgetNumTwo = new QWidget; disWidgetNumTwo->setFixedHeight(30); disWidgetNumTwo->setObjectName("OriginObjectOnly"); disWidgetNumTwo->setLayout(twovolume_h_BoxLayout); disWidgetNumTwo->installEventFilter(this); QHBoxLayout *threevolume_h_BoxLayout = new QHBoxLayout(); m_nameDis3_label = new ClickLabel(this); m_nameDis3_label->setFont(QFont("Microsoft YaHei",fontSize)); QString VolumeNameDis3 = getElidedText(m_nameDis3_label->font(), m_nameDis3, 120); m_nameDis3_label->setText("- "+VolumeNameDis3+":"); m_nameDis3_label->adjustSize(); m_nameDis3_label->installEventFilter(this); m_capacityDis3_label = new QLabel(this); QString str_capacityDis3 = size_human(m_capacityDis3); m_capacityDis3_label->setText("("+str_capacityDis3+")"); m_capacityDis3_label->setFont(QFont("Microsoft YaHei",fontSize)); m_capacityDis3_label->setObjectName("capacityLabel"); threevolume_h_BoxLayout->addSpacing(50); threevolume_h_BoxLayout->setSpacing(0); threevolume_h_BoxLayout->addWidget(m_nameDis3_label); threevolume_h_BoxLayout->addWidget(m_capacityDis3_label); threevolume_h_BoxLayout->addStretch(); threevolume_h_BoxLayout->setMargin(0); disWidgetNumThree = new QWidget; disWidgetNumThree->setFixedHeight(30); disWidgetNumThree->setObjectName("OriginObjectOnly"); disWidgetNumThree->setLayout(threevolume_h_BoxLayout); disWidgetNumThree->installEventFilter(this); main_V_BoxLayout->setContentsMargins(0,0,0,0); main_V_BoxLayout->addLayout(drivename_H_BoxLayout); if(m_pathDis1 != "") { main_V_BoxLayout->addWidget(disWidgetNumOne); } if(m_pathDis2 != "") { main_V_BoxLayout->addWidget(disWidgetNumTwo); } if(m_pathDis3 != "") { main_V_BoxLayout->addWidget(disWidgetNumThree); } this->setLayout(main_V_BoxLayout); this->setFixedSize(276,136); } //when the drive has four volumes if(m_Num == 4) { QHBoxLayout *onevolume_h_BoxLayout = new QHBoxLayout(); m_nameDis1_label = new ClickLabel(this); m_nameDis1_label->setFont(QFont("Microsoft YaHei",fontSize)); QString VolumeNameDis1 = getElidedText(m_nameDis1_label->font(), m_nameDis1, 120); m_nameDis1_label->setText("- "+VolumeNameDis1+":"); m_nameDis1_label->adjustSize(); m_nameDis1_label->installEventFilter(this); //m_nameDis1_label->setText("- "+m_nameDis1+":"); m_capacityDis1_label = new QLabel(this); QString str_capacityDis1 = size_human(m_capacityDis1); m_capacityDis1_label->setText("("+str_capacityDis1+")"); m_capacityDis1_label->setFont(QFont("Microsoft YaHei",fontSize)); m_capacityDis1_label->setObjectName("capacityLabel"); onevolume_h_BoxLayout->addSpacing(50); onevolume_h_BoxLayout->setSpacing(0); onevolume_h_BoxLayout->addWidget(m_nameDis1_label); onevolume_h_BoxLayout->addWidget(m_capacityDis1_label); onevolume_h_BoxLayout->addStretch(); onevolume_h_BoxLayout->setMargin(0); disWidgetNumOne = new QWidget; disWidgetNumOne->setFixedHeight(30); disWidgetNumOne->setObjectName("OriginObjectOnly"); disWidgetNumOne->setLayout(onevolume_h_BoxLayout); disWidgetNumOne->installEventFilter(this); QHBoxLayout *twovolume_h_BoxLayout = new QHBoxLayout(); m_nameDis2_label = new ClickLabel(this); m_nameDis2_label->setFont(QFont("Microsoft YaHei",fontSize)); QString VolumeNameDis2 = getElidedText(m_nameDis2_label->font(), m_nameDis2, 120); m_nameDis2_label->setText("- "+VolumeNameDis2+":"); m_nameDis2_label->installEventFilter(this); m_nameDis2_label->adjustSize(); m_nameDis2_label->installEventFilter(this); //m_nameDis2_label->setText("- "+m_nameDis2+":"); m_capacityDis2_label = new QLabel(this); QString str_capacityDis2 = size_human(m_capacityDis2); m_capacityDis2_label->setText("("+str_capacityDis2+")"); m_capacityDis2_label->setFont(QFont("Microsoft YaHei",fontSize)); m_capacityDis2_label->setObjectName("capacityLabel"); twovolume_h_BoxLayout->addSpacing(50); twovolume_h_BoxLayout->setSpacing(0); twovolume_h_BoxLayout->addWidget(m_nameDis2_label); twovolume_h_BoxLayout->addWidget(m_capacityDis2_label); twovolume_h_BoxLayout->addStretch(); twovolume_h_BoxLayout->setMargin(0); disWidgetNumTwo = new QWidget; disWidgetNumTwo->setFixedHeight(30); disWidgetNumTwo->setObjectName("OriginObjectOnly"); disWidgetNumTwo->setLayout(twovolume_h_BoxLayout); disWidgetNumTwo->installEventFilter(this); QHBoxLayout *threevolume_h_BoxLayout = new QHBoxLayout(); m_nameDis3_label = new ClickLabel(this); m_nameDis3_label->setFont(QFont("Microsoft YaHei",fontSize)); QString VolumeNameDis3 = getElidedText(m_nameDis3_label->font(), m_nameDis3, 120); m_nameDis3_label->setText("- "+VolumeNameDis3+":"); m_nameDis3_label->installEventFilter(this); m_capacityDis3_label = new QLabel(this); QString str_capacityDis3 = size_human(m_capacityDis3); m_capacityDis3_label->setText("("+str_capacityDis3+")"); m_capacityDis3_label->setFont(QFont("Microsoft YaHei",fontSize)); m_capacityDis3_label->setObjectName("capacityLabel"); threevolume_h_BoxLayout->addSpacing(50); threevolume_h_BoxLayout->setSpacing(0); threevolume_h_BoxLayout->addWidget(m_nameDis3_label); threevolume_h_BoxLayout->addWidget(m_capacityDis3_label); threevolume_h_BoxLayout->addStretch(0); threevolume_h_BoxLayout->setMargin(0); disWidgetNumThree = new QWidget; disWidgetNumThree->setFixedHeight(30); disWidgetNumThree->setObjectName("OriginObjectOnly"); disWidgetNumThree->setLayout(threevolume_h_BoxLayout); disWidgetNumThree->installEventFilter(this); QHBoxLayout *fourvolume_h_BoxLayout = new QHBoxLayout(); m_nameDis4_label = new ClickLabel(this); m_nameDis4_label->setFont(QFont("Microsoft YaHei",fontSize)); QString VolumeNameDis4 = getElidedText(m_nameDis4_label->font(), m_nameDis4, 120); m_nameDis4_label->setText("- "+VolumeNameDis4+":"); m_nameDis4_label->adjustSize(); m_nameDis4_label->installEventFilter(this); //m_nameDis4_label->setText("- "+m_nameDis4+":"); m_capacityDis4_label = new QLabel(this); QString str_capacityDis4 = size_human(m_capacityDis4); m_capacityDis4_label->setText("("+str_capacityDis4+")"); m_capacityDis4_label->setFont(QFont("Microsoft YaHei",fontSize)); m_capacityDis4_label->setObjectName("capacityLabel"); fourvolume_h_BoxLayout->addSpacing(50); fourvolume_h_BoxLayout->setSpacing(0); fourvolume_h_BoxLayout->addWidget(m_nameDis4_label); fourvolume_h_BoxLayout->addWidget(m_capacityDis4_label); fourvolume_h_BoxLayout->addStretch(); fourvolume_h_BoxLayout->setMargin(0); disWidgetNumFour = new QWidget; disWidgetNumFour->setFixedHeight(30); disWidgetNumFour->setObjectName("OriginObjectOnly"); disWidgetNumFour->setLayout(fourvolume_h_BoxLayout); disWidgetNumFour->installEventFilter(this); main_V_BoxLayout->setContentsMargins(0,0,0,0); main_V_BoxLayout->addLayout(drivename_H_BoxLayout); if(m_pathDis1 != "") { main_V_BoxLayout->addWidget(disWidgetNumOne); } if(m_pathDis2 != "") { main_V_BoxLayout->addWidget(disWidgetNumTwo); } if(m_pathDis3 != "") { main_V_BoxLayout->addWidget(disWidgetNumThree); } if(m_pathDis4 != "") { main_V_BoxLayout->addWidget(disWidgetNumFour); } this->setLayout(main_V_BoxLayout); this->setFixedSize(276,165); } qDebug()<<"4444"; this->setAttribute(Qt::WA_TranslucentBackground, true); qDebug()<<"qlcked overeend"; } void QClickWidget::initFontSize() { if (!fontSettings) { fontSize = 11; return; } QStringList keys = fontSettings->keys(); if (keys.contains("systemFont") || keys.contains("systemFontSize")) { fontSize = fontSettings->get("system-font").toInt(); } } void QClickWidget::initThemeMode() { if(!qtSettings) { currentThemeMode = "ukui-white"; } QStringList keys = qtSettings->keys(); if(keys.contains("styleName")) { currentThemeMode = qtSettings->get("style-name").toString(); } } QClickWidget::~QClickWidget() { if(chooseDialog) delete chooseDialog; if(gpartedface) delete gpartedface; } void QClickWidget::mouseClicked() { QProcess::startDetached("peony "+m_pathDis1); this->topLevelWidget()->hide(); } void QClickWidget::mousePressEvent(QMouseEvent *ev) { mousePos = QPoint(ev->x(), ev->y()); } void QClickWidget::mouseReleaseEvent(QMouseEvent *ev) { if(mousePos == QPoint(ev->x(), ev->y())) Q_EMIT clicked(); } //click the first area to show the interface void QClickWidget::on_volume1_clicked() { if (!m_pathDis1.isEmpty()) { QString aaa = "peony "+m_pathDis1; QProcess::startDetached(aaa.toUtf8().data()); this->topLevelWidget()->hide(); } } //click the second area to show the interface void QClickWidget::on_volume2_clicked() { if (!m_pathDis2.isEmpty()) { QString aaa = "peony "+m_pathDis2; QProcess::startDetached(aaa.toUtf8().data()); this->topLevelWidget()->hide(); } } //click the third area to show the interface void QClickWidget::on_volume3_clicked() { if (!m_pathDis3.isEmpty()) { QProcess::startDetached("peony "+m_pathDis3); this->topLevelWidget()->hide(); } } //click the forth area to show the interface void QClickWidget::on_volume4_clicked() { if (!m_pathDis4.isEmpty()) { QProcess::startDetached("peony "+m_pathDis4); this->topLevelWidget()->hide(); } } void QClickWidget::switchWidgetClicked() { Q_EMIT clickedConvert(); } QPixmap QClickWidget::drawSymbolicColoredPixmap(const QPixmap &source) { if(currentThemeMode == "ukui-light" || currentThemeMode == "ukui-white") { QImage img = source.toImage(); for (int x = 0; x < img.width(); x++) { for (int y = 0; y < img.height(); y++) { auto color = img.pixelColor(x, y); if (color.alpha() > 0) { color.setRed(0); color.setGreen(0); color.setBlue(0); img.setPixelColor(x, y, color); } } } return QPixmap::fromImage(img); } else if(currentThemeMode == "ukui-dark" || currentThemeMode == "ukui-black" || currentThemeMode == "ukui-default" ) { QImage img = source.toImage(); for (int x = 0; x < img.width(); x++) { for (int y = 0; y < img.height(); y++) { auto color = img.pixelColor(x, y); if (color.alpha() > 0) { color.setRed(255); color.setGreen(255); color.setBlue(255); img.setPixelColor(x, y, color); } } } return QPixmap::fromImage(img); } else { QImage img = source.toImage(); for (int x = 0; x < img.width(); x++) { for (int y = 0; y < img.height(); y++) { auto color = img.pixelColor(x, y); if (color.alpha() > 0) { color.setRed(0); color.setGreen(0); color.setBlue(0); img.setPixelColor(x, y, color); } } } return QPixmap::fromImage(img); } } //to convert the capacity by another type QString QClickWidget::size_human(qlonglong capacity) { // float capacity = this->size(); if(capacity != 0 && capacity != 1) { int conversionNum = 0; QStringList list; list << "KB" << "MB" << "GB" << "TB"; QStringListIterator i(list); QString unit("bytes"); qlonglong conversion = capacity; while(conversion >= 1000.0 && i.hasNext()) { unit = i.next(); conversion /= 1000.0; conversionNum++; } qlonglong remain = capacity - conversion * qPow(1000,conversionNum); float showRemain; if(conversionNum == 3) { showRemain = (float)remain /1000/1000/1000; } if(conversionNum == 2) { showRemain = (float)remain /1000/1000; } if(conversionNum == 1) { showRemain = (float)remain /1000; } double showValue = conversion + showRemain; QString str2=QString::number(showValue,'f',1); QString str_capacity=QString(" %1%2").arg(str2).arg(unit); return str_capacity; // return QString().setNum(capacity,'f',2)+" "+unit; } #if (QT_VERSION < QT_VERSION_CHECK(5,7,0)) if(capacity == NULL) { QString str_capaticity = tr("the capacity is empty"); return str_capaticity; } #endif if(capacity == 1) { QString str_capacity = tr("blank CD"); return str_capacity; } QString str_capacity = tr("other user device"); return str_capacity; } //set the style of the eject button and label when the mouse doing some different operations bool QClickWidget::eventFilter(QObject *obj, QEvent *event) { if(obj == m_eject_button) { if(event->type() == QEvent::MouseButtonPress) { if(currentThemeMode == "ukui-dark" || currentThemeMode == "ukui-black" || currentThemeMode == "ukui-default") { m_eject_button->setIconSize(QSize(14,14)); m_eject_button->setFixedSize(38,38); m_eject_button->setStyleSheet( "background:rgba(255,255,255,0.08);" "border-radius:4px;" ); } else { m_eject_button->setIconSize(QSize(14,14)); m_eject_button->setFixedSize(38,38); m_eject_button->setStyleSheet( "background:rgba(0,0,0,0.08);" "border-radius:4px;" ); } } if(event->type() == QEvent::Enter) { if(currentThemeMode == "ukui-dark" || currentThemeMode == "ukui-black" || currentThemeMode == "ukui-default") { m_eject_button->setIconSize(QSize(16,16)); m_eject_button->setFixedSize(40,40); m_eject_button->setStyleSheet( "background-color:rgba(255,255,255,0.91);" "background:rgba(255,255,255,0.12);" "border-radius:4px;"); } else { m_eject_button->setIconSize(QSize(16,16)); m_eject_button->setFixedSize(40,40); m_eject_button->setStyleSheet( "background-color:rgba(0,0,0,0.91);" "background:rgba(0,0,0,0.12);" "border-radius:4px;"); } } if(event->type() == QEvent::Leave) { if(currentThemeMode == "ukui-dark" || currentThemeMode == "ukui-black") { m_eject_button->setIconSize(QSize(16,16)); m_eject_button->setFixedSize(40,40); m_eject_button->setStyleSheet( "background-color:rgba(255,255,255,0.75);" "background-color:rgba(255,255,255,0.57);" "background:rgba(255,255,255,0);" "border-radius:4px;"); } else { m_eject_button->setIconSize(QSize(16,16)); m_eject_button->setFixedSize(40,40); m_eject_button->setStyleSheet( "background-color:rgba(0,0,0,0.75);" "background-color:rgba(0,0,0,0.57);" "background:rgba(0,0,0,0);" "border-radius:4px;"); } } } if(obj == disWidgetNumOne) { if(event->type() == QEvent::Enter) { if(currentThemeMode == "ukui-dark" || currentThemeMode == "ukui-black" || currentThemeMode == "ukui-default") { disWidgetNumOne->setStyleSheet( "QWidget#OriginObjectOnly{background:rgba(255,255,255,0.12);}"); } else { disWidgetNumOne->setStyleSheet( "QWidget#OriginObjectOnly{background:rgba(0,0,0,0.12);}"); } } if(event->type() == QEvent::Leave) { disWidgetNumOne->setStyleSheet(""); } if(event->type() == QEvent::MouseButtonPress) { on_volume1_clicked(); } } if(obj == disWidgetNumTwo) { if(event->type() == QEvent::Enter ) { if(currentThemeMode == "ukui-dark" || currentThemeMode == "ukui-black" || currentThemeMode == "ukui-default") { disWidgetNumTwo->setStyleSheet( "QWidget#OriginObjectOnly{background:rgba(255,255,255,0.12);}"); } else { disWidgetNumTwo->setStyleSheet( "QWidget#OriginObjectOnly{background:rgba(0,0,0,0.12);}"); } } if(event->type() == QEvent::Leave) { disWidgetNumTwo->setStyleSheet(""); } if(event->type() == QEvent::MouseButtonPress) { on_volume2_clicked(); } } if(obj == disWidgetNumThree) { if(event->type() == QEvent::Enter ) { if(currentThemeMode == "ukui-dark" || currentThemeMode == "ukui-black" || currentThemeMode == "ukui-default") { disWidgetNumThree->setStyleSheet( "QWidget#OriginObjectOnly{background:rgba(255,255,255,0.12);}"); } else { disWidgetNumThree->setStyleSheet( "QWidget#OriginObjectOnly{background:rgba(0,0,0,0.12);}"); } } if(event->type() == QEvent::Leave) { disWidgetNumThree->setStyleSheet(""); } if(event->type() == QEvent::MouseButtonPress) { on_volume3_clicked(); } } if(obj == disWidgetNumFour) { if(event->type() == QEvent::Enter ) { if(currentThemeMode == "ukui-dark" || currentThemeMode == "ukui-black" || currentThemeMode == "ukui-default") { disWidgetNumFour->setStyleSheet( "QWidget#OriginObjectOnly{background:rgba(255,255,255,0.12);}"); } else { disWidgetNumFour->setStyleSheet( "QWidget#OriginObjectOnly{background:rgba(0,0,0,0.12);}"); } } if(event->type() == QEvent::Leave) { disWidgetNumFour->setStyleSheet(""); } if(event->type() == QEvent::MouseButtonPress) { on_volume4_clicked(); } } return false; } void QClickWidget::resizeEvent(QResizeEvent *event) { } ukui-panel-3.0.6.4/ukui-flash-disk/picture/0000755000175000017500000000000014203402514017022 5ustar fengfengukui-panel-3.0.6.4/ukui-flash-disk/picture/drive-removable-media.svg0000755000175000017500000000306214203402514023707 0ustar fengfeng ukui-panel-3.0.6.4/ukui-flash-disk/picture/media-eject-symbolic.svg0000644000175000017500000000044414203402514023533 0ustar fengfeng画板 1ukui-panel-3.0.6.4/ukui-flash-disk/picture/drive-removable-media-usb.png0000644000175000017500000000072614203402514024464 0ustar fengfengPNG  IHDR szz pHYs  ~IDATXc?@Bvnȅ3gPxPuA5q.q;?CZ03 oe9X~AdQpf4Cy%@IpSZ n.8bK2\z}xO|fvTd8(-瓇$L^~{ɰ-'7,1zlAr__bHMbxËo/ɶ*v=NjYdPUFز#UFONCHf][ gZ w=K7000inc~t`1 INn߆eed'Obj$;60ho//ĈC'000!+MIENDB`ukui-panel-3.0.6.4/ukui-flash-disk/datacdrom.h0000644000175000017500000000551314203402514017462 0ustar fengfeng/* * Peony-Qt's Library * * Copyright (C) 2020, KylinSoft Co., Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this library. If not, see . * * Authors: renpeijia * */ #ifndef DATACDROM_H #define DATACDROM_H #include #include #include enum MEDIUM_TYPE { MEDIUM_UNKOWN = 0x0000, MEDIUM_CD_ROM = 0x0001, MEDIUM_CD_R = 0x0002, MEDIUM_CD_RW = 0x0004, MEDIUM_DVD_ROM = 0x0008, MEDIUM_DVD_R = 0x0010, MEDIUM_DVD_RAM = 0x0020, MEDIUM_DVD_R_DL_SEQ = 0x0040, MEDIUM_DVD_R_DL_JUMP = 0x0080, MEDIUM_DVD_PLUS_RW = 0x0100, MEDIUM_DVD_PLUS_R = 0x0101, MEDIUM_DVD_PLUS_RW_DL = 0x0102, MEDIUM_DVD_PLUS_R_DL = 0x0104, MEDIUM_DVD_RW_OVERWRITE = 0x0108, MEDIUM_DVD_RW_SEQ = 0x0110, MEDIUM_CD_RW_S0 = 0x0120, // in MMC-5 CD-RW has 8 subtypes. MEDIUM_CD_RW_S1 = 0x0140, MEDIUM_CD_RW_S2 = 0x0180, MEDIUM_CD_RW_S3 = 0x0200, MEDIUM_CD_RW_S4 = 0x0201, MEDIUM_CD_RW_S5 = 0x0202, MEDIUM_CD_RW_S6 = 0x0204, MEDIUM_CD_RW_S7 = 0x0208, MEDIUM_DVD_RW = 0x0210 }; enum MEDIUM_STATUS { MEDIUM_EMPTY = 0, MEDIUM_INCOMPLETE, MEDIUM_FINALIZED, MEDIUM_OTHER }; enum BURN_MODE { BURN_CD_TAO = 0x01, BURN_CD_SAO = 0x02, BURN_CD_DAO = 0x04 // close session/track when TAO over. }; class DataCDROM : public QObject { Q_OBJECT public: explicit DataCDROM(QString &blockName, QObject *parent = nullptr); ~DataCDROM(); public: void getCDROMInfo(); unsigned long getCDROMCapacity() { return m_u64Capacity; } unsigned long getCDROMUsedCapacity() { return m_u64UsedCapacity; } private: bool open(); void close(); bool execSCSI(const unsigned char *, const int, unsigned char *, const int); int checkRWSupport(); int checkMediumType(); int cdRomGetTrackNum(); void DVDRWCapacity(); void cdRomCapacity(); private: int m_iHandle; unsigned int m_u32MediumRSupport; unsigned int m_u32MediumWSupport; QString m_oBlockName; QString m_oMediumType; unsigned int m_u32TrackNumber; unsigned long m_u64UsedCapacity; unsigned long m_u64FreeCapacity; unsigned long m_u64Capacity; }; #endif // DATACDROM_H ukui-panel-3.0.6.4/ukui-flash-disk/mainwindow.cpp0000755000175000017500000042272414203402514020245 0ustar fengfeng /* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include #include #include #include #include #include #include #include #include #include "clickLabel.h" #include "MacroFile.h" #include "datacdrom.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) , findPointMount(false) , telephoneNum(0) , driveVolumeNum(0) , m_strSysRootDev(QString("")) { ui->setupUi(this); initThemeMode(); initFlashDisk(); initSlots(); installEventFilter(this); // get system root device getSystemRootDev(); // underlying code to get the information of the usb device getDeviceInfo(); } MainWindow::~MainWindow() { delete ui; if (m_transparency_gsettings) { delete m_transparency_gsettings; m_transparency_gsettings = nullptr; } if (ifsettings) { delete ifsettings; ifsettings = nullptr; } } void MainWindow::initFlashDisk() { m_vtDeviveId.clear(); // 框架的样式设置 // set the style of the framework interfaceHideTime = new QTimer(this); initTransparentState(); ui->centralWidget->setObjectName("centralWidget"); vboxlayout = new QVBoxLayout(this); ui->centralWidget->setLayout(vboxlayout); #if (QT_VERSION < QT_VERSION_CHECK(5,7,0)) this->setWindowFlags(Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint); #else this->setWindowFlags(Qt::FramelessWindowHint | Qt::Popup); #endif this->setAttribute(Qt::WA_TranslucentBackground); m_systray = new QSystemTrayIcon(this); m_systray->setIcon(QIcon::fromTheme("media-removable-symbolic")); //m_systray->setVisible(true); m_systray->setToolTip(tr("usb management tool")); // init the screen screen = qApp->primaryScreen(); m_nAppStartTimestamp = QDateTime::currentDateTime().toMSecsSinceEpoch(); m_dataFlashDisk = FlashDiskData::getInstance(); } void MainWindow::initSlots() { connect(m_systray, &QSystemTrayIcon::activated, this, &MainWindow::iconActivated); connect(this, &MainWindow::convertShowWindow, this, &MainWindow::onConvertShowWindow); connect(this, &MainWindow::convertUpdateWindow, this, &MainWindow::onConvertUpdateWindow); connect(this, &MainWindow::remountVolume, this, &MainWindow::onRemountVolume); connect(this, &MainWindow::checkDriveValid, this, &MainWindow::onCheckDriveValid); connect(this, &MainWindow::notifyDeviceRemoved, this, &MainWindow::onNotifyDeviceRemoved); connect(m_dataFlashDisk, &FlashDiskData::notifyDeviceRemoved, this, &MainWindow::onNotifyDeviceRemoved); QDBusConnection::sessionBus().connect(QString(), QString("/taskbar/click"), \ "com.ukui.panel.plugins.taskbar", "sendToUkuiDEApp", this, SLOT(on_clickPanelToHideInterface())); connect(this, SIGNAL(deviceError(GDrive*)), this, SLOT(onDeviceErrored(GDrive*)), (Qt::UniqueConnection)); connect(this, SIGNAL(mountVolume(GVolume*)), this, SLOT(onMountVolume(GVolume*))); connect(this, SIGNAL(ejectVolumeForce(GVolume*)), this, SLOT(onEjectVolumeForce(GVolume*))); connect(interfaceHideTime, SIGNAL(timeout()), this, SLOT(onMaininterfacehide())); } void MainWindow::onRequestSendDesktopNotify(QString message, QString strIcon) { QDBusInterface iface("org.freedesktop.Notifications", "/org/freedesktop/Notifications", "org.freedesktop.Notifications", QDBusConnection::sessionBus()); QList args; args << (tr("ukui flash disk")) << ((unsigned int) 0) << strIcon << tr("kindly reminder") //显示的是什么类型的信息 << message //显示的具体信息 << QStringList() << QVariantMap() << (int)-1; iface.callWithArgumentList(QDBus::NoBlock,"Notify",args); } void MainWindow::onInsertAbnormalDiskNotify(QString message) { QDBusInterface iface("org.freedesktop.Notifications", "/org/freedesktop/Notifications", "org.freedesktop.Notifications", QDBusConnection::sessionBus()); QList args; args << (tr("ukui flash disk")) << ((unsigned int) 0) << QString("media-removable-symbolic") << tr("wrong reminder") //显示的是什么类型的信息 << message //显示的具体信息 << QStringList() << QVariantMap() << (int)-1; iface.callWithArgumentList(QDBus::NoBlock,"Notify",args); } void MainWindow::onNotifyWnd(QObject* obj, QEvent *event) { QString strObjName(obj->metaObject()->className()); if (strObjName == "QSystemTrayIconSys") { if (!m_bIsMouseInTraIcon && event->type() == QEvent::Enter) { if (interfaceHideTime->isActive()) { interfaceHideTime->stop(); } m_bIsMouseInTraIcon = true; } else if (m_bIsMouseInTraIcon && event->type() == QEvent::Leave) { if (!m_bIsMouseInCentral) { interfaceHideTime->start(2000); } m_bIsMouseInTraIcon = false; } } else if (obj == ui->centralWidget) { if (!m_bIsMouseInCentral && event->type() == QEvent::Enter) { interfaceHideTime->stop(); ui->centralWidget->show(); m_bIsMouseInCentral = true; } else if (m_bIsMouseInCentral && event->type() == QEvent::Leave) { if (!m_bIsMouseInTraIcon) { interfaceHideTime->start(2000); } m_bIsMouseInCentral = false; } } } void MainWindow::initThemeMode() { const QByteArray idd(THEME_QT_SCHEMA); if(QGSettings::isSchemaInstalled(idd)) { QGSettings *qtSettings = new QGSettings(idd, QByteArray(), this); connect(qtSettings,&QGSettings::changed,this,[=](const QString &key) { currentThemeMode = qtSettings->get(MODE_QT_KEY).toString(); }); currentThemeMode = qtSettings->get(MODE_QT_KEY).toString(); } const QByteArray id(AUTOLOAD); if(QGSettings::isSchemaInstalled(idd)) { ifsettings = new QGSettings(id); } } void MainWindow::on_clickPanelToHideInterface() { if(!ui->centralWidget->isHidden()) { ui->centralWidget->hide(); } } void MainWindow::getSystemRootDev() { QString cmd = "df -l"; QProcess *p = new QProcess(); p->start(cmd); p->waitForFinished(); while(p->canReadLine()) { QString str = p->readLine(); QStringList infoList = str.split(QRegExp("\\s+")); if (infoList.size() >= 6) { if (infoList[5] == "/") { m_strSysRootDev = infoList[0]; break; } } } delete p; p = nullptr; } bool MainWindow::isSystemRootDev(QString strDev) { return m_strSysRootDev.startsWith(strDev); } void MainWindow::getDeviceInfo() { // setting FILE *fp = NULL; int a = 0; char buf[128] = {0}; fp = fopen("/proc/cmdline","r"); if(fp) { while(fscanf(fp,"%127s",buf) >0 ) { if(strcmp(buf,"live") == 0) { a++; } } fclose(fp); } if(a > 0) { QProcess::startDetached("gsettings set org.ukui.flash-disk.autoload ifautoload false"); } // callback function that to monitor the insertion and removal of the underlying equipment GVolumeMonitor *g_volume_monitor = g_volume_monitor_get(); g_signal_connect (g_volume_monitor, "drive-connected", G_CALLBACK (drive_connected_callback), this); g_signal_connect (g_volume_monitor, "drive-disconnected", G_CALLBACK (drive_disconnected_callback), this); g_signal_connect (g_volume_monitor, "volume-added", G_CALLBACK (volume_added_callback), this); g_signal_connect (g_volume_monitor, "volume-removed", G_CALLBACK (volume_removed_callback), this); g_signal_connect (g_volume_monitor, "mount-added", G_CALLBACK (mount_added_callback), this); g_signal_connect (g_volume_monitor, "mount-removed", G_CALLBACK (mount_removed_callback), this); GList *lDrive = NULL, *lVolume = NULL, *lMount = NULL; // about drive GList *current_drive_list = g_volume_monitor_get_connected_drives(g_volume_monitor); for (lDrive = current_drive_list; lDrive != NULL; lDrive = lDrive->next) { GDrive *gdrive = (GDrive *)lDrive->data; char *devPath = g_drive_get_identifier(gdrive,G_DRIVE_IDENTIFIER_KIND_UNIX_DEVICE); if (devPath != NULL) { FDDriveInfo driveInfo; driveInfo.strId = devPath; char *strName = g_drive_get_name(gdrive); if (strName) { driveInfo.strName = strName; g_free(strName); } getDriveIconsInfo(gdrive, driveInfo); driveInfo.isCanEject = g_drive_can_eject(gdrive); driveInfo.isCanStop = g_drive_can_stop(gdrive); driveInfo.isCanStart = g_drive_can_start(gdrive); driveInfo.isRemovable = g_drive_is_removable(gdrive); if(!isSystemRootDev(driveInfo.strId.c_str()) && (driveInfo.isCanEject || driveInfo.isCanStop || driveInfo.isRemovable)) { if(g_str_has_prefix(devPath,"/dev/sr") || g_str_has_prefix(devPath,"/dev/bus") || g_str_has_prefix(devPath,"/dev/sd") || g_str_has_prefix(devPath,"/dev/mmcblk")) { GList* gdriveVolumes = g_drive_get_volumes(gdrive); if (gdriveVolumes) { for(lVolume = gdriveVolumes; lVolume != NULL; lVolume = lVolume->next){ //遍历驱动器上的所有卷设备 GVolume* volume = (GVolume *)lVolume->data; FDVolumeInfo volumeInfo; bool isValidMount = true; char *volumeId = g_volume_get_identifier(volume,G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE); if (volumeId) { volumeInfo.strId = volumeId; g_free(volumeId); } else { continue ; } char *volumeName = g_volume_get_name(volume); if (volumeName) { volumeInfo.strName = volumeName; g_free(volumeName); } char *strDevName = g_volume_get_identifier(volume,G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE); if (strDevName) { volumeInfo.strDevName = strDevName; g_free(strDevName); } getVolumeIconsInfo(volume, volumeInfo); volumeInfo.isCanMount = g_volume_can_mount(volume); volumeInfo.isCanEject = g_volume_can_eject(volume); volumeInfo.isShouldAutoMount = g_volume_should_automount(volume); GMount* mount = g_volume_get_mount(volume); //get当前卷设备的挂载信息 if (mount) { //该卷设备已挂载 volumeInfo.mountInfo.isCanEject = g_mount_can_eject(mount); volumeInfo.mountInfo.isCanUnmount = g_mount_can_unmount(mount); if (volumeInfo.mountInfo.isCanEject || volumeInfo.mountInfo.isCanUnmount) { char *mountId = g_mount_get_uuid(mount); if (mountId) { volumeInfo.mountInfo.strId = mountId; g_free(mountId); } char *mountName = g_mount_get_name(mount); if (mountName) { volumeInfo.mountInfo.strName = mountName; g_free(mountName); } // get mount total size GFile *fileRoot = g_mount_get_root(mount); if (fileRoot) { GFileInfo *info = g_file_query_filesystem_info(fileRoot,G_FILE_ATTRIBUTE_FILESYSTEM_SIZE,nullptr,nullptr); if (info) { volumeInfo.mountInfo.lluTotalSize = g_file_info_get_attribute_uint64(info,G_FILE_ATTRIBUTE_FILESYSTEM_SIZE); g_object_unref(info); } g_object_unref(fileRoot); } getDataCDRomCapacity(volumeInfo.strId.c_str(),volumeInfo.mountInfo.lluTotalSize); // get mount uri GFile *root = g_mount_get_default_location(mount); if (root) { volumeInfo.mountInfo.isNativeDev = g_file_is_native(root); //判断设备是本地设备or网络设备 char *mountUri = g_file_get_uri(root); //get挂载点的uri路径 if (mountUri) { volumeInfo.mountInfo.strUri = mountUri; if (g_str_has_prefix(mountUri,"file:///data")) { isValidMount = false; } else { if (volumeInfo.mountInfo.strId.empty()) { volumeInfo.mountInfo.strId = volumeInfo.mountInfo.strUri; } } g_free(mountUri); } char *tooltip = g_file_get_parse_name(root); //提示,即文件的解释 if (tooltip) { volumeInfo.mountInfo.strTooltip =tooltip; g_free(tooltip); } g_object_unref(root); } getMountIconsInfo(mount, volumeInfo.mountInfo); } g_object_unref(mount); } else { if(ifsettings->get(IFAUTOLOAD).toBool()) { g_volume_mount(volume, G_MOUNT_MOUNT_NONE, nullptr, nullptr, nullptr, nullptr); } } if (isValidMount) { driveInfo.listVolumes[volumeInfo.strId] = volumeInfo; } } g_list_free(gdriveVolumes); } m_dataFlashDisk->addDriveInfo(driveInfo); } } g_free(devPath); } } if (current_drive_list) { g_list_free(current_drive_list); } // about volume not associated with a drive GList *current_volume_list = g_volume_monitor_get_volumes(g_volume_monitor); if (current_volume_list) { for (lVolume = current_volume_list; lVolume != NULL; lVolume = lVolume->next) { GVolume *volume = (GVolume *)lVolume->data; GDrive *gdrive = g_volume_get_drive(volume); if (!gdrive) { FDVolumeInfo volumeInfo; bool isValidMount = true; char *devPath = g_volume_get_identifier(volume,G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE); if (devPath) { if (!(g_str_has_prefix(devPath,"/dev/sr") || g_str_has_prefix(devPath,"/dev/bus") || g_str_has_prefix(devPath,"/dev/sd") || g_str_has_prefix(devPath,"/dev/mmcblk"))) { g_free(devPath); continue; } g_free(devPath); } char *volumeId = g_volume_get_identifier(volume,G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE); if (volumeId) { volumeInfo.strId = volumeId; g_free(volumeId); } else { continue ; } char *volumeName = g_volume_get_name(volume); if (volumeName) { volumeInfo.strName = volumeName; g_free(volumeName); } char *strDevName = g_volume_get_identifier(volume,G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE); if (strDevName) { volumeInfo.strDevName = strDevName; g_free(strDevName); } getVolumeIconsInfo(volume, volumeInfo); volumeInfo.isCanMount = g_volume_can_mount(volume); volumeInfo.isCanEject = g_volume_can_eject(volume); volumeInfo.isShouldAutoMount = g_volume_should_automount(volume); GMount* mount = g_volume_get_mount(volume); //get当前卷设备的挂载信息 if (mount) { //该卷设备已挂载 volumeInfo.mountInfo.isCanEject = g_mount_can_eject(mount); volumeInfo.mountInfo.isCanUnmount = g_mount_can_unmount(mount); if (volumeInfo.mountInfo.isCanEject || volumeInfo.mountInfo.isCanUnmount) { char *mountId = g_mount_get_uuid(mount); if (mountId) { volumeInfo.mountInfo.strId = mountId; g_free(mountId); } char *mountName = g_mount_get_name(mount); if (mountName) { volumeInfo.mountInfo.strName = mountName; g_free(mountName); } // get mount total size GFile *fileRoot = g_mount_get_root(mount); if (fileRoot) { GFileInfo *info = g_file_query_filesystem_info(fileRoot,G_FILE_ATTRIBUTE_FILESYSTEM_SIZE,nullptr,nullptr); if (info) { volumeInfo.mountInfo.lluTotalSize = g_file_info_get_attribute_uint64(info,G_FILE_ATTRIBUTE_FILESYSTEM_SIZE); g_object_unref(info); } g_object_unref(fileRoot); } getDataCDRomCapacity(volumeInfo.strId.c_str(),volumeInfo.mountInfo.lluTotalSize); // get mount uri GFile *root = g_mount_get_default_location(mount); if (root) { volumeInfo.mountInfo.isNativeDev = g_file_is_native(root); //判断设备是本地设备or网络设备 char *mountUri = g_file_get_uri(root); //get挂载点的uri路径 if (mountUri) { volumeInfo.mountInfo.strUri = mountUri; if (g_str_has_prefix(mountUri,"file:///data")) { isValidMount = false; } else { if (volumeInfo.mountInfo.strId.empty()) { volumeInfo.mountInfo.strId = volumeInfo.mountInfo.strUri; } } g_free(mountUri); } char *tooltip = g_file_get_parse_name(root); //提示,即文件的解释 if (tooltip) { volumeInfo.mountInfo.strTooltip =tooltip; g_free(tooltip); } g_object_unref(root); } getMountIconsInfo(mount, volumeInfo.mountInfo); } g_object_unref(mount); } else { if (volumeInfo.isCanMount) { if(ifsettings->get(IFAUTOLOAD).toBool()) { g_volume_mount(volume, G_MOUNT_MOUNT_NONE, nullptr, nullptr, nullptr, nullptr); } } } if (isValidMount) { m_dataFlashDisk->addVolumeInfo(volumeInfo); } } else { g_object_unref(gdrive); } } g_list_free(current_volume_list); } // about mount not associated with a volume GList *current_mount_list = g_volume_monitor_get_mounts(g_volume_monitor); if (current_mount_list) { for (lMount = current_mount_list; lMount != NULL; lMount = lMount->next) { GMount *gmount = (GMount *)lMount->data; GVolume *gvolume = g_mount_get_volume(gmount); if (!gvolume) { GDrive* gdrive = g_mount_get_drive(gmount); if (gdrive) { char *devPath = g_drive_get_identifier(gdrive,G_DRIVE_IDENTIFIER_KIND_UNIX_DEVICE); if (devPath != NULL) { FDDriveInfo driveInfo; driveInfo.strId = devPath; char *strName = g_drive_get_name(gdrive); if (strName) { driveInfo.strName = strName; g_free(strName); } getDriveIconsInfo(gdrive, driveInfo); driveInfo.isCanEject = g_drive_can_eject(gdrive); driveInfo.isCanStop = g_drive_can_stop(gdrive); driveInfo.isCanStart = g_drive_can_start(gdrive); driveInfo.isRemovable = g_drive_is_removable(gdrive); if(!isSystemRootDev(driveInfo.strId.c_str()) && (driveInfo.isCanEject || driveInfo.isCanStop || driveInfo.isRemovable)) { if(g_str_has_prefix(devPath,"/dev/sr") || g_str_has_prefix(devPath,"/dev/bus") || g_str_has_prefix(devPath,"/dev/sd") || g_str_has_prefix(devPath,"/dev/mmcblk")) { FDMountInfo mountInfo; bool isValidMount = true; mountInfo.isCanEject = g_mount_can_eject(gmount); mountInfo.isCanUnmount = g_mount_can_unmount(gmount); if (mountInfo.isCanEject || mountInfo.isCanUnmount) { char *mountId = g_mount_get_uuid(gmount); if (mountId) { mountInfo.strId = mountId; g_free(mountId); } char *mountName = g_mount_get_name(gmount); if (mountName) { mountInfo.strName = mountName; g_free(mountName); } // get mount total size GFile *fileRoot = g_mount_get_root(gmount); if (fileRoot) { GFileInfo *info = g_file_query_filesystem_info(fileRoot,G_FILE_ATTRIBUTE_FILESYSTEM_SIZE,nullptr,nullptr); if (info) { mountInfo.lluTotalSize = g_file_info_get_attribute_uint64(info,G_FILE_ATTRIBUTE_FILESYSTEM_SIZE); g_object_unref(info); } g_object_unref(fileRoot); } getDataCDRomCapacity(driveInfo.strId.c_str(),mountInfo.lluTotalSize); // get mount uri GFile *root = g_mount_get_default_location(gmount); if (root) { mountInfo.isNativeDev = g_file_is_native(root); //判断设备是本地设备or网络设备 char *mountUri = g_file_get_uri(root); //get挂载点的uri路径 if (mountUri) { mountInfo.strUri = mountUri; if (g_str_has_prefix(mountUri,"file:///data")) { isValidMount = false; } else { if (mountInfo.strId.empty()) { mountInfo.strId = mountInfo.strUri; } } g_free(mountUri); } char *tooltip = g_file_get_parse_name(root); //提示,即文件的解释 if (tooltip) { mountInfo.strTooltip =tooltip; g_free(tooltip); } g_object_unref(root); } getMountIconsInfo(gmount, mountInfo); if (isValidMount) { FDVolumeInfo volumeInfo; volumeInfo.mountInfo = mountInfo; m_dataFlashDisk->addMountInfoWithDrive(driveInfo, volumeInfo, mountInfo); } } } } g_free(devPath); } g_object_unref(gdrive); } else { # if 0 FDMountInfo mountInfo; bool isValidMount = true; mountInfo.isCanEject = g_mount_can_eject(gmount); mountInfo.isCanUnmount = g_mount_can_unmount(gmount); if (mountInfo.isCanEject || mountInfo.isCanUnmount) { char *mountId = g_mount_get_uuid(gmount); if (mountId) { mountInfo.strId = mountId; g_free(mountId); } char *mountName = g_mount_get_name(gmount); if (mountName) { mountInfo.strName = mountName; g_free(mountName); } // get mount total size GFile *fileRoot = g_mount_get_root(gmount); if (fileRoot) { GFileInfo *info = g_file_query_filesystem_info(fileRoot,G_FILE_ATTRIBUTE_FILESYSTEM_SIZE,nullptr,nullptr); if (info) { mountInfo.lluTotalSize = g_file_info_get_attribute_uint64(info,G_FILE_ATTRIBUTE_FILESYSTEM_SIZE); g_object_unref(info); } g_object_unref(fileRoot); } getDataCDRomCapacity(mountInfo.strId.c_str(),mountInfo.lluTotalSize); // get mount uri GFile *root = g_mount_get_default_location(gmount); if (root) { mountInfo.isNativeDev = g_file_is_native(root); //判断设备是本地设备or网络设备 char *mountUri = g_file_get_uri(root); //get挂载点的uri路径 if (mountUri) { mountInfo.strUri = mountUri; if (g_str_has_prefix(mountUri,"file:///data")) { isValidMount = false; } else { if (mountInfo.strId.empty()) { mountInfo.strId = mountInfo.strUri; } } g_free(mountUri); } char *tooltip = g_file_get_parse_name(root); //提示,即文件的解释 if (tooltip) { mountInfo.strTooltip =tooltip; g_free(tooltip); } g_object_unref(root); } if (isValidMount) { m_dataFlashDisk->addMountInfo(mountInfo); } } #endif } } else { g_object_unref(gvolume); } } g_list_free(current_mount_list); } // determine the systray icon should be showed or be hieded if(m_dataFlashDisk->getValidInfoCount() >= 1) { m_systray->show(); } else { m_systray->hide(); } m_dataFlashDisk->OutputInfos(); } void MainWindow::onConvertShowWindow(QString strDriveId, QString strMountUri) { // 进程启动时一定时间内不弹窗提示 if (QDateTime::currentDateTime().toMSecsSinceEpoch() - m_nAppStartTimestamp < NEWINFO_DELAYSHOW_TIME) { m_dataFlashDisk->resetAllNewState(); return; } insertorclick = true; MainWindowShow(); string strDeviceId = strDriveId.toStdString(); if (std::find(m_vtDeviveId.begin(), m_vtDeviveId.end(), strDeviceId) == m_vtDeviveId.end()) { #if IFDISTINCT_DEVICON QString strIcon = m_dataFlashDisk->getVolumeIcon(strDriveId); onRequestSendDesktopNotify(tr("Please do not pull out the storage device when reading or writing"), strIcon); #else if (strDriveId.startsWith("/dev/sr")) { onRequestSendDesktopNotify(tr("Please do not pull out the CDROM when reading or writing"), QString("media-removable-symbolic")); } else if (strDriveId.startsWith("/dev/mmcblk")) { onRequestSendDesktopNotify(tr("Please do not pull out the SD Card when reading or writing"), QString("media-removable-symbolic")); } else { onRequestSendDesktopNotify(tr("Please do not pull out the USB flash disk when reading or writing"), QString("drive-removable-media-usb")); } #endif m_vtDeviveId.push_back(strDeviceId); } } void MainWindow::onNotifyDeviceRemoved(QString strDevId) { if (strDevId.isEmpty()) { return; } #if IFDISTINCT_DEVICON QString strIcon = m_dataFlashDisk->getVolumeIcon(strDevId); onRequestSendDesktopNotify(tr("Storage device removed"), strIcon); #else if (strDevId.startsWith("/dev/sr")) { onRequestSendDesktopNotify(tr("Storage device removed"), QString("media-removable-symbolic")); } else if (strDevId.startsWith("/dev/mmcblk")) { onRequestSendDesktopNotify(tr("Storage device removed"), QString("media-removable-symbolic")); } else { onRequestSendDesktopNotify(tr("Storage device removed"), QString("drive-removable-media-usb")); } #endif } void MainWindow::onConvertUpdateWindow(QString strDevName, unsigned uDevType) { // uDevType: 0 drive , 1 volume, 2 mount if (uDevType != 0) { // not drive detached insertorclick = true; MainWindowShow(true); } } // the drive-connected callback function the is triggered when the usb device is inseted void MainWindow::drive_connected_callback(GVolumeMonitor *monitor, GDrive *drive, MainWindow *p_this) { qInfo() << "drive add"; if(p_this->ifsettings->get(IFAUTOLOAD).toBool()) { GList *lVolume = NULL; FDDriveInfo driveInfo; GDrive *gdrive = (GDrive *)drive; unsigned uSubVolumeSize = 0; char *devPath = g_drive_get_identifier(gdrive,G_DRIVE_IDENTIFIER_KIND_UNIX_DEVICE); if (devPath != NULL) { driveInfo.strId = devPath; char *strName = g_drive_get_name(gdrive); if (strName) { driveInfo.strName = strName; g_free(strName); } driveInfo.isCanEject = g_drive_can_eject(gdrive); driveInfo.isCanStop = g_drive_can_stop(gdrive); driveInfo.isCanStart = g_drive_can_start(gdrive); driveInfo.isRemovable = g_drive_is_removable(gdrive); g_free(devPath); } if (!g_drive_has_volumes(gdrive)) { QTimer::singleShot(1000, p_this, [&,driveInfo,p_this]() { p_this->onCheckDriveValid(driveInfo); }); } lVolume = g_drive_get_volumes(gdrive); if (lVolume) { uSubVolumeSize = g_list_length(lVolume); g_list_free(lVolume); } p_this->getDriveIconsInfo(gdrive, driveInfo); if (!driveInfo.strId.empty()) { p_this->m_dataFlashDisk->addDriveInfo(driveInfo); } // perhaps uSubVolumeSize is 0 and is ok ? // else { // qInfo()<<"wrong disk has intered"; // p_this->onInsertAbnormalDiskNotify(tr("There is a problem with this device")); // } } if(p_this->m_dataFlashDisk->getValidInfoCount() >= 1) { p_this->m_systray->show(); } p_this->triggerType = 0; p_this->m_dataFlashDisk->OutputInfos(); } // the drive-disconnected callback function the is triggered when the usb device is pull out void MainWindow::drive_disconnected_callback (GVolumeMonitor *monitor, GDrive *drive, MainWindow *p_this) { qInfo() << "drive disconnect"; FDDriveInfo driveInfo; char *devPath = g_drive_get_identifier(drive,G_DRIVE_IDENTIFIER_KIND_UNIX_DEVICE); if (devPath != NULL) { driveInfo.strId = devPath; g_free(devPath); } vector::iterator itDeviceId = p_this->m_vtDeviveId.begin(); for (; itDeviceId != p_this->m_vtDeviveId.end();) { if (driveInfo.strId == *itDeviceId) { itDeviceId = p_this->m_vtDeviveId.erase(itDeviceId); } else { itDeviceId++; } } p_this->m_dataFlashDisk->removeDriveInfo(driveInfo); if(p_this->m_dataFlashDisk->getValidInfoCount() == 0) { p_this->ui->centralWidget->hide(); p_this->m_systray->hide(); } p_this->m_dataFlashDisk->OutputInfos(); } // when the usb device is identified, we should mount every partition void MainWindow::volume_added_callback(GVolumeMonitor *monitor, GVolume *volume, MainWindow *p_this) { qDebug() << "volume add"; GDrive* gdrive = g_volume_get_drive(volume); FILE *fp = NULL; int a = 0; char buf[128] = {0}; fp = fopen("/proc/cmdline","r"); if (fp) { while(fscanf(fp,"%127s",buf) > 0) { if(strcmp(buf,"live") == 0) { a++; } } fclose(fp); } p_this->ifautoload = p_this->ifsettings->get(IFAUTOLOAD).toBool(); if(a > 0) { QProcess::startDetached("gsettings set org.ukui.flash-disk.autoload ifautoload false"); } else { //QProcess::startDetached("gsettings set org.ukui.flash-disk.autoload ifautoload true"); } bool isNewMount = false; if(!gdrive) { FDVolumeInfo volumeInfo; bool isValidMount = true; char *devPath = g_volume_get_identifier(volume,G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE); if (devPath) { if (!(g_str_has_prefix(devPath,"/dev/sr") || g_str_has_prefix(devPath,"/dev/bus") || g_str_has_prefix(devPath,"/dev/sd") || g_str_has_prefix(devPath,"/dev/mmcblk"))) { g_free(devPath); return; } g_free(devPath); } char *volumeId = g_volume_get_identifier(volume,G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE); if (volumeId) { volumeInfo.strId = volumeId; g_free(volumeId); } else { return ; } char *volumeName = g_volume_get_name(volume); if (volumeName) { volumeInfo.strName = volumeName; g_free(volumeName); } char *strDevName = g_volume_get_identifier(volume,G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE); if (strDevName) { volumeInfo.strDevName = strDevName; g_free(strDevName); } p_this->getVolumeIconsInfo(volume, volumeInfo); volumeInfo.isCanMount = g_volume_can_mount(volume); volumeInfo.isCanEject = g_volume_can_eject(volume); volumeInfo.isShouldAutoMount = g_volume_should_automount(volume); GMount* mount = g_volume_get_mount(volume); //get当前卷设备的挂载信息 if (mount) { //该卷设备已挂载 volumeInfo.mountInfo.isCanEject = g_mount_can_eject(mount); volumeInfo.mountInfo.isCanUnmount = g_mount_can_unmount(mount); if (volumeInfo.mountInfo.isCanEject || volumeInfo.mountInfo.isCanUnmount) { char *mountId = g_mount_get_uuid(mount); if (mountId) { volumeInfo.mountInfo.strId = mountId; g_free(mountId); } char *mountName = g_mount_get_name(mount); if (mountName) { volumeInfo.mountInfo.strName = mountName; g_free(mountName); } isNewMount = !(p_this->m_dataFlashDisk->isMountInfoExist(volumeInfo.mountInfo)); // get mount total size GFile *fileRoot = g_mount_get_root(mount); if (fileRoot) { GFileInfo *info = g_file_query_filesystem_info(fileRoot,G_FILE_ATTRIBUTE_FILESYSTEM_SIZE,nullptr,nullptr); if (info) { volumeInfo.mountInfo.lluTotalSize = g_file_info_get_attribute_uint64(info,G_FILE_ATTRIBUTE_FILESYSTEM_SIZE); g_object_unref(info); } g_object_unref(fileRoot); } p_this->getDataCDRomCapacity(volumeInfo.strId.c_str(), volumeInfo.mountInfo.lluTotalSize); // get mount uri GFile *root = g_mount_get_default_location(mount); if (root) { volumeInfo.mountInfo.isNativeDev = g_file_is_native(root); //判断设备是本地设备or网络设备 char *mountUri = g_file_get_uri(root); //get挂载点的uri路径 if (mountUri) { volumeInfo.mountInfo.strUri = mountUri; if (g_str_has_prefix(mountUri,"file:///data")) { isValidMount = false; } else { if (volumeInfo.mountInfo.strId.empty()) { volumeInfo.mountInfo.strId = volumeInfo.mountInfo.strUri; } } g_free(mountUri); } char *tooltip = g_file_get_parse_name(root); //提示,即文件的解释 if (tooltip) { volumeInfo.mountInfo.strTooltip = tooltip; g_free(tooltip); } g_object_unref(root); } p_this->getMountIconsInfo(mount, volumeInfo.mountInfo); } g_object_unref(mount); } else { if (volumeInfo.isCanMount) { if(p_this->ifsettings->get(IFAUTOLOAD).toBool()) { g_volume_mount(volume, G_MOUNT_MOUNT_NONE, nullptr, nullptr, GAsyncReadyCallback(frobnitz_result_func_volume), p_this); } } } if (isValidMount) { p_this->m_dataFlashDisk->addVolumeInfo(volumeInfo); } } else { char *devPath = g_drive_get_identifier(gdrive,G_DRIVE_IDENTIFIER_KIND_UNIX_DEVICE); if (devPath != NULL) { FDDriveInfo driveInfo; FDVolumeInfo volumeInfo; driveInfo.strId = devPath; char *strName = g_drive_get_name(gdrive); if (strName) { driveInfo.strName = strName; g_free(strName); } p_this->getDriveIconsInfo(gdrive, driveInfo); driveInfo.isCanEject = g_drive_can_eject(gdrive); driveInfo.isCanStop = g_drive_can_stop(gdrive); driveInfo.isCanStart = g_drive_can_start(gdrive); driveInfo.isRemovable = g_drive_is_removable(gdrive); if(!p_this->isSystemRootDev(driveInfo.strId.c_str()) && (driveInfo.isCanEject || driveInfo.isCanStop || driveInfo.isRemovable)) { if(g_str_has_prefix(devPath,"/dev/sr") || g_str_has_prefix(devPath,"/dev/bus") || g_str_has_prefix(devPath,"/dev/sd") || g_str_has_prefix(devPath,"/dev/mmcblk")) { char *volumeId = g_volume_get_identifier(volume,G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE); if (volumeId) { volumeInfo.strId = volumeId; g_free(volumeId); char *volumeName = g_volume_get_name(volume); if (volumeName) { volumeInfo.strName = volumeName; g_free(volumeName); } char *strDevName = g_volume_get_identifier(volume,G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE); if (strDevName) { volumeInfo.strDevName = strDevName; g_free(strDevName); } p_this->getVolumeIconsInfo(volume, volumeInfo); volumeInfo.isCanMount = g_volume_can_mount(volume); volumeInfo.isCanEject = g_volume_can_eject(volume); volumeInfo.isShouldAutoMount = g_volume_should_automount(volume); GMount* mount = g_volume_get_mount(volume); //get当前卷设备的挂载信息 if (mount) { //该卷设备已挂载 volumeInfo.mountInfo.isCanEject = g_mount_can_eject(mount); volumeInfo.mountInfo.isCanUnmount = g_mount_can_unmount(mount); if (volumeInfo.mountInfo.isCanEject || volumeInfo.mountInfo.isCanUnmount) { char *mountId = g_mount_get_uuid(mount); if (mountId) { volumeInfo.mountInfo.strId = mountId; g_free(mountId); } char *mountName = g_mount_get_name(mount); if (mountName) { volumeInfo.mountInfo.strName = mountName; g_free(mountName); } isNewMount = !(p_this->m_dataFlashDisk->isMountInfoExist(volumeInfo.mountInfo)); // get mount total size GFile *fileRoot = g_mount_get_root(mount); if (fileRoot) { GFileInfo *info = g_file_query_filesystem_info(fileRoot,G_FILE_ATTRIBUTE_FILESYSTEM_SIZE,nullptr,nullptr); if (info) { volumeInfo.mountInfo.lluTotalSize = g_file_info_get_attribute_uint64(info,G_FILE_ATTRIBUTE_FILESYSTEM_SIZE); g_object_unref(info); } g_object_unref(fileRoot); } p_this->getDataCDRomCapacity(volumeInfo.strId.c_str(), volumeInfo.mountInfo.lluTotalSize); // get mount uri GFile *root = g_mount_get_default_location(mount); if (root) { volumeInfo.mountInfo.isNativeDev = g_file_is_native(root); //判断设备是本地设备or网络设备 char *mountUri = g_file_get_uri(root); //get挂载点的uri路径 if (mountUri) { volumeInfo.mountInfo.strUri = mountUri; if (!g_str_has_prefix(mountUri,"file:///data")) { if (volumeInfo.mountInfo.strId.empty()) { volumeInfo.mountInfo.strId = volumeInfo.mountInfo.strUri; } } g_free(mountUri); } char *tooltip = g_file_get_parse_name(root); //提示,即文件的解释 if (tooltip) { volumeInfo.mountInfo.strTooltip =tooltip; g_free(tooltip); } g_object_unref(root); } p_this->getMountIconsInfo(mount, volumeInfo.mountInfo); } g_object_unref(mount); } else { if(p_this->ifsettings->get(IFAUTOLOAD).toBool()) { g_volume_mount(volume, G_MOUNT_MOUNT_NONE, nullptr, nullptr, GAsyncReadyCallback(frobnitz_result_func_volume), p_this); } } } } if (isNewMount) { //qInfo()<<"cd data disk has mounted!"; volumeInfo.isNewInsert = true; p_this->m_dataFlashDisk->addVolumeInfoWithDrive(driveInfo, volumeInfo); string strDevId = driveInfo.strId.empty()?volumeInfo.strId:driveInfo.strId; Q_EMIT p_this->convertShowWindow(strDevId.c_str(), volumeInfo.mountInfo.strUri.c_str()); } else { p_this->m_dataFlashDisk->addVolumeInfoWithDrive(driveInfo, volumeInfo); } } g_free(devPath); } g_object_unref(gdrive); } if(p_this->m_dataFlashDisk->getValidInfoCount() > 0) { p_this->m_systray->show(); } p_this->m_dataFlashDisk->OutputInfos(); } // when the U disk is pull out we should reduce all its partitions void MainWindow::volume_removed_callback(GVolumeMonitor *monitor, GVolume *volume, MainWindow *p_this) { qInfo() << "volume removed"; FDVolumeInfo volumeInfo; char *volumeId = g_volume_get_identifier(volume,G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE); if (volumeId) { volumeInfo.strId = volumeId; g_free(volumeId); } char *strName = g_volume_get_name(volume); if (strName) { volumeInfo.strName = strName; g_free(strName); } vector::iterator itDeviceId = p_this->m_vtDeviveId.begin(); for (; itDeviceId != p_this->m_vtDeviveId.end();) { if (volumeInfo.strId == *itDeviceId) { itDeviceId = p_this->m_vtDeviveId.erase(itDeviceId); } else { itDeviceId++; } } p_this->m_dataFlashDisk->removeVolumeInfo(volumeInfo); if(p_this->m_dataFlashDisk->getValidInfoCount() == 0) { p_this->m_systray->hide(); } p_this->m_dataFlashDisk->OutputInfos(); Q_EMIT p_this->convertUpdateWindow(QString::fromStdString(volumeInfo.strName), 1); //emit a signal to update the MainMainShow slot } // when the volumes were mounted we add its mounts number void MainWindow::mount_added_callback(GVolumeMonitor *monitor, GMount *mount, MainWindow *p_this) { qInfo() << "mount add"; GDrive* gdrive = g_mount_get_drive(mount); GVolume* gvolume = g_mount_get_volume(mount); string strVolumePath = ""; FDDriveInfo driveInfo; FDVolumeInfo volumeInfo; FDMountInfo mountInfo; bool isValidMount = true; if (gdrive) { char *devPath = g_drive_get_identifier(gdrive,G_DRIVE_IDENTIFIER_KIND_UNIX_DEVICE); if (devPath != NULL) { driveInfo.strId = devPath; char *strName = g_drive_get_name(gdrive); if (strName) { driveInfo.strName = strName; g_free(strName); } p_this->getDriveIconsInfo(gdrive, driveInfo); driveInfo.isCanEject = g_drive_can_eject(gdrive); driveInfo.isCanStop = g_drive_can_stop(gdrive); driveInfo.isCanStart = g_drive_can_start(gdrive); driveInfo.isRemovable = g_drive_is_removable(gdrive); g_free(devPath); } g_object_unref(gdrive); } if (gvolume) { char *volumeId = g_volume_get_identifier(gvolume,G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE); char *devVolumePath = g_volume_get_identifier(gvolume,G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE); if (devVolumePath) { strVolumePath = devVolumePath; g_free(devVolumePath); } if (volumeId) { volumeInfo.strId = volumeId; g_free(volumeId); char *volumeName = g_volume_get_name(gvolume); if (volumeName) { volumeInfo.strName = volumeName; g_free(volumeName); } char *strDevName = g_volume_get_identifier(gvolume,G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE); if (strDevName) { volumeInfo.strDevName = strDevName; g_free(strDevName); } p_this->getVolumeIconsInfo(gvolume, volumeInfo); volumeInfo.isCanMount = g_volume_can_mount(gvolume); volumeInfo.isCanEject = g_volume_can_eject(gvolume); volumeInfo.isShouldAutoMount = g_volume_should_automount(gvolume); } g_object_unref(gvolume); } mountInfo.isCanEject = g_mount_can_eject(mount); char *mountId = g_mount_get_uuid(mount); if (mountId) { mountInfo.strId = mountId; g_free(mountId); } char *mountName = g_mount_get_name(mount); if (mountName) { mountInfo.strName = mountName; g_free(mountName); } mountInfo.isCanUnmount = g_mount_can_unmount(mount); GFile *root = g_mount_get_default_location(mount); // get mount total size GFile *fileRoot = g_mount_get_root(mount); if (fileRoot) { unsigned uRetryTime = 5; unsigned uDelayTime = 200000; while (uRetryTime > 0) { GFileInfo *info = g_file_query_filesystem_info(fileRoot,G_FILE_ATTRIBUTE_FILESYSTEM_SIZE,nullptr,nullptr); if (info) { mountInfo.lluTotalSize = g_file_info_get_attribute_uint64(info,G_FILE_ATTRIBUTE_FILESYSTEM_SIZE); g_object_unref(info); break; } else { usleep(uDelayTime); } uRetryTime --; } g_object_unref(fileRoot); } p_this->getDataCDRomCapacity(driveInfo.strId.empty()?volumeInfo.strId.c_str():driveInfo.strId.c_str(), mountInfo.lluTotalSize); // get mount uri if (root) { mountInfo.isNativeDev = g_file_is_native(root); //判断设备是本地设备or网络设备 char *mountUri = g_file_get_uri(root); //get挂载点的uri路径 if (mountUri) { mountInfo.strUri = mountUri; if (g_str_has_prefix(mountUri,"file:///data")) { isValidMount = false; } else { if (mountInfo.strId.empty()) { mountInfo.strId = mountInfo.strUri; } } g_free(mountUri); } char *tooltip = g_file_get_parse_name(root); //提示,即文件的解释 if (tooltip) { mountInfo.strTooltip = tooltip; g_free(tooltip); } g_object_unref(root); } p_this->getMountIconsInfo(mount, mountInfo); if (driveInfo.strId.empty()) { Q_EMIT p_this->telephoneMount(); } bool isNewMount = !(p_this->m_dataFlashDisk->isMountInfoExist(mountInfo)); if (!driveInfo.strId.empty()) { if (p_this->isSystemRootDev(driveInfo.strId.c_str()) || (!driveInfo.isCanEject && !driveInfo.isCanStop && !driveInfo.isRemovable)) { isValidMount = false; } } if (volumeInfo.strId.empty()) { // 没有卷信息的挂载不处理(ftp等) isValidMount = false; } if(isValidMount && (mountInfo.isCanUnmount || g_str_has_prefix(strVolumePath.c_str(),"/dev/bus") || g_str_has_prefix(strVolumePath.c_str(),"/dev/sr") || g_str_has_prefix(strVolumePath.c_str(),"/dev/mmcblk"))) { qInfo() << "real mount loaded"; mountInfo.isNewInsert = true; if (!driveInfo.strId.empty()) { if (!volumeInfo.strId.empty()) { volumeInfo.mountInfo = mountInfo; p_this->m_dataFlashDisk->addVolumeInfoWithDrive(driveInfo, volumeInfo); } else { p_this->m_dataFlashDisk->addMountInfo(mountInfo); } } else if (!volumeInfo.strId.empty()) { volumeInfo.mountInfo = mountInfo; p_this->m_dataFlashDisk->addVolumeInfo(volumeInfo); } else { p_this->m_dataFlashDisk->addMountInfo(mountInfo); } } else { qInfo()<<"不符合过滤条件的设备已被挂载"; } if(p_this->m_dataFlashDisk->getValidInfoCount() >= 1) { if (isValidMount && isNewMount) { //qInfo()<<"cd data disk has mounted!"; string strDevId = driveInfo.strId.empty()?volumeInfo.strId:driveInfo.strId; Q_EMIT p_this->convertShowWindow(strDevId.c_str(), mountInfo.strUri.c_str()); } p_this->m_systray->show(); } p_this->m_dataFlashDisk->OutputInfos(); } // when the mountes were uninstalled we reduce mounts number void MainWindow::mount_removed_callback(GVolumeMonitor *monitor, GMount *mount, MainWindow *p_this) { qInfo() << mount << "mount remove"; FDMountInfo mountInfo; mountInfo.isCanEject = g_mount_can_eject(mount); char *mountId = g_mount_get_uuid(mount); if (mountId) { mountInfo.strId = mountId; g_free(mountId); } char *mountName = g_mount_get_name(mount); if (mountName) { mountInfo.strName = mountName; g_free(mountName); } mountInfo.isCanUnmount = g_mount_can_unmount(mount); GFile *root = g_mount_get_default_location(mount); if (root) { mountInfo.isNativeDev = g_file_is_native(root); //判断设备是本地设备or网络设备 char *mountUri = g_file_get_uri(root); //get挂载点的uri路径 if (mountUri) { mountInfo.strUri = mountUri; g_free(mountUri); if (mountInfo.strId.empty()) { mountInfo.strId = mountInfo.strUri; } } char *tooltip = g_file_get_parse_name(root); //提示,即文件的解释 if (tooltip) { mountInfo.strTooltip = tooltip; g_free(tooltip); } g_object_unref(root); } // check mount's volume had removed? FDVolumeInfo volumeInfo; p_this->m_dataFlashDisk->getVolumeInfoByMount(mountInfo, volumeInfo); quint64 mountTickDiff = p_this->m_dataFlashDisk->getMountTickDiff(mountInfo); p_this->m_dataFlashDisk->removeMountInfo(mountInfo); if(p_this->m_dataFlashDisk->getValidInfoCount() == 0) { p_this->m_systray->hide(); } p_this->m_dataFlashDisk->OutputInfos(); Q_EMIT p_this->convertUpdateWindow(QString::fromStdString(mountInfo.strName), 2); //emit a signal to update the MainMainShow slot qInfo()<<"ID:"< 0 && mountTickDiff < 500 && !volumeInfo.strId.empty()) { QTimer::singleShot(1000, p_this, [&,volumeInfo,p_this]() { p_this->onRemountVolume(volumeInfo); }); } } // it stands that when you insert a usb device when all the U disk partitions void MainWindow::frobnitz_result_func_volume(GVolume *source_object,GAsyncResult *res,MainWindow *p_this) { gboolean success = FALSE; GError *err = nullptr; bool bMountSuccess = false; success = g_volume_mount_finish (source_object, res, &err); if(!err) { GMount* gmount = g_volume_get_mount(source_object); GDrive* gdrive = g_volume_get_drive(source_object); FDDriveInfo driveInfo; FDVolumeInfo volumeInfo; FDMountInfo mountInfo; if (gdrive) { char *devPath = g_drive_get_identifier(gdrive,G_DRIVE_IDENTIFIER_KIND_UNIX_DEVICE); if (devPath != NULL) { driveInfo.strId = devPath; char *strName = g_drive_get_name(gdrive); if (strName) { driveInfo.strName = strName; g_free(strName); } p_this->getDriveIconsInfo(gdrive, driveInfo); driveInfo.isCanEject = g_drive_can_eject(gdrive); driveInfo.isCanStop = g_drive_can_stop(gdrive); driveInfo.isCanStart = g_drive_can_start(gdrive); driveInfo.isRemovable = g_drive_is_removable(gdrive); g_free(devPath); } g_object_unref(gdrive); } char *volumeId = g_volume_get_identifier(source_object,G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE); if (volumeId) { volumeInfo.strId = volumeId; g_free(volumeId); char *volumeName = g_volume_get_name(source_object); if (volumeName) { volumeInfo.strName = volumeName; g_free(volumeName); } char *strDevName = g_volume_get_identifier(source_object,G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE); if (strDevName) { volumeInfo.strDevName = strDevName; g_free(strDevName); } p_this->getVolumeIconsInfo(source_object, volumeInfo); volumeInfo.isCanMount = g_volume_can_mount(source_object); volumeInfo.isCanEject = g_volume_can_eject(source_object); volumeInfo.isShouldAutoMount = g_volume_should_automount(source_object); } if (gmount) { bMountSuccess = true; mountInfo.isCanEject = g_mount_can_eject(gmount); char *mountId = g_mount_get_uuid(gmount); if (mountId) { mountInfo.strId = mountId; g_free(mountId); } char *mountName = g_mount_get_name(gmount); if (mountName) { mountInfo.strName = mountName; g_free(mountName); } mountInfo.isCanUnmount = g_mount_can_unmount(gmount); // get mount total size GFile *fileRoot = g_mount_get_root(gmount); if (fileRoot) { unsigned uRetryTime = 5; unsigned uDelayTime = 200000; while (uRetryTime > 0) { GFileInfo *info = g_file_query_filesystem_info(fileRoot,G_FILE_ATTRIBUTE_FILESYSTEM_SIZE,nullptr,nullptr); if (info) { mountInfo.lluTotalSize = g_file_info_get_attribute_uint64(info,G_FILE_ATTRIBUTE_FILESYSTEM_SIZE); g_object_unref(info); break; } else { usleep(uDelayTime); } uRetryTime --; } g_object_unref(fileRoot); } p_this->getDataCDRomCapacity(driveInfo.strId.empty()?volumeInfo.strId.c_str():driveInfo.strId.c_str(), mountInfo.lluTotalSize); // get mount uri GFile *root = g_mount_get_default_location(gmount); if (root) { mountInfo.isNativeDev = g_file_is_native(root); //判断设备是本地设备or网络设备 char *mountUri = g_file_get_uri(root); //get挂载点的uri路径 if (mountUri) { mountInfo.strUri = mountUri; if (g_str_has_prefix(mountUri,"file:///data")) { bMountSuccess = false; }else { if (mountInfo.strId.empty()) { mountInfo.strId = mountInfo.strUri; } } g_free(mountUri); } char *tooltip = g_file_get_parse_name(root); //提示,即文件的解释 if (tooltip) { mountInfo.strTooltip = tooltip; g_free(tooltip); } g_object_unref(root); } p_this->getMountIconsInfo(gmount, mountInfo); g_object_unref(gmount); } if (bMountSuccess) { mountInfo.isNewInsert = true; bool isNewMount = !(p_this->m_dataFlashDisk->isMountInfoExist(mountInfo)); if (!driveInfo.strId.empty()) { if (!volumeInfo.strId.empty()) { volumeInfo.mountInfo = mountInfo; p_this->m_dataFlashDisk->addVolumeInfoWithDrive(driveInfo, volumeInfo); } else { p_this->m_dataFlashDisk->addMountInfo(mountInfo); } } else if (!volumeInfo.strId.empty()) { volumeInfo.mountInfo = mountInfo; p_this->m_dataFlashDisk->addVolumeInfo(volumeInfo); } else { p_this->m_dataFlashDisk->addMountInfo(mountInfo); } if (isNewMount) { qInfo()<<"sig has emitted"; string strDevId = driveInfo.strId.empty()?volumeInfo.strId:driveInfo.strId; Q_EMIT p_this->convertShowWindow(strDevId.c_str(), mountInfo.strUri.c_str()); //emit a signal to trigger the MainMainShow slot } } } else if (G_IO_ERROR_ALREADY_MOUNTED == err->code) { } else if (G_IO_ERROR_UNKNOWN == err->code) { } else { qInfo()<<"sorry mount failed"<code<<","<message; GDrive* gdrive = g_volume_get_drive(source_object); Q_EMIT p_this->deviceError(gdrive); if (nullptr != gdrive) { g_object_unref(gdrive); } } } // here we begin painting the main interface void MainWindow::iconActivated(QSystemTrayIcon::ActivationReason reason) { triggerType = 1; //It represents how we open the interface if (ui->centralWidget && !ui->centralWidget->isHidden() && !insertorclick) { ui->centralWidget->hide(); return ; } insertorclick = false; MainWindowShow(); } void MainWindow::hideEvent(QHideEvent event) { // delete open_widget; } /* * newarea use all the information of the U disk to paint the main interface and add line */ void MainWindow::newarea(int No, GDrive *Drive, GVolume *Volume, QString Drivename, QString nameDis1, QString nameDis2, QString nameDis3, QString nameDis4, qlonglong capacityDis1, qlonglong capacityDis2, qlonglong capacityDis3, qlonglong capacityDis4, QString pathDis1, QString pathDis2, QString pathDis3, QString pathDis4, int linestatus) { open_widget = new QClickWidget(ui->centralWidget,No,Drive,Volume,Drivename,nameDis1,nameDis2,nameDis3,nameDis4, capacityDis1,capacityDis2,capacityDis3,capacityDis4, pathDis1,pathDis2,pathDis3,pathDis4); connect(open_widget,&QClickWidget::clickedConvert,this,[=]() { ui->centralWidget->hide(); }); connect(open_widget,&QClickWidget::noDeviceSig,this,[=]() { m_systray->hide(); }); line = new QWidget; line->setFixedHeight(1); line->setObjectName("lineWidget"); if(currentThemeMode == "ukui-dark" || currentThemeMode == "ukui-black" || currentThemeMode == "ukui-default" || currentThemeMode == "ukui") { line->setStyleSheet("background-color:rgba(255,255,255,0.2);"); } else { line->setStyleSheet("background-color:rgba(0,0,0,0.2);"); } //when the drive is only or the drive is the first one,we make linestatus become 1 line->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); line->setFixedSize(276,1); if (linestatus == 2) { this->vboxlayout->addWidget(line); } vboxlayout->setContentsMargins(2,4,2,4); vboxlayout->setSpacing(0); vboxlayout->setMargin(0); this->vboxlayout->addWidget(open_widget); if (linestatus == 0) { this->vboxlayout->addWidget(line); } } void MainWindow::newarea(unsigned uDiskNo, QString strDriveId, QString strVolumeId, QString strMountId, QString driveName, QString volumeName, quint64 capacityDis, QString strMountUri, int linestatus) { m_fdClickWidget = new FDClickWidget(ui->centralWidget,uDiskNo,strDriveId,strVolumeId,strMountId, driveName,volumeName,capacityDis,strMountUri); connect(m_fdClickWidget, &FDClickWidget::clickedEject,this,&MainWindow::onClickedEject); line = new QWidget; line->setFixedHeight(1); line->setObjectName("lineWidget"); if(currentThemeMode == "ukui-dark" || currentThemeMode == "ukui-black" || currentThemeMode == "ukui-default" || currentThemeMode == "ukui") { line->setStyleSheet("background-color:rgba(255,255,255,0.2);"); } else { line->setStyleSheet("background-color:rgba(0,0,0,0.2);"); } // when the drive is only or the drive is the first one,we make linestatus become 1 line->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); line->setFixedSize(276,1); if (linestatus == 2) { this->vboxlayout->addWidget(line); } vboxlayout->setContentsMargins(2,4,2,4); //vboxlayout->setSpacing(0); //vboxlayout->setMargin(0); this->vboxlayout->addWidget(m_fdClickWidget); if (linestatus == 0) { this->vboxlayout->addWidget(line); } } void MainWindow::moveBottomRight() { //MARGIN 为到任务栏或屏幕边缘的间隔 #define MARGIN 4 QDBusInterface iface("org.ukui.panel", "/panel/position", "org.ukui.panel", QDBusConnection::sessionBus()); QDBusReply reply=iface.call("GetPrimaryScreenGeometry"); //reply获取的参数共5个,分别是 主屏可用区域的起点x坐标,主屏可用区域的起点y坐标,主屏可用区域的宽度,主屏可用区域高度,任务栏位置 // reply.value(); qInfo()<setGeometry(position_list.at(0).toInt()+position_list.at(2).toInt()-this->width()-MARGIN, position_list.at(1).toInt()+MARGIN, this->width(),this->height()); break; //任务栏位于左边 case 2: this->setGeometry(position_list.at(0).toInt()+MARGIN, position_list.at(1).toInt()+reply.value().at(3).toInt()-this->height()-MARGIN, this->width(),this->height()); break; //任务栏位于右边 case 3: this->setGeometry(position_list.at(0).toInt()+position_list.at(2).toInt()-this->width()-MARGIN, position_list.at(1).toInt()+reply.value().at(3).toInt()-this->height()-MARGIN, this->width(),this->height()); break; //任务栏位于下方 default: this->setGeometry(position_list.at(0).toInt()+position_list.at(2).toInt()-this->width()-MARGIN, position_list.at(1).toInt()+reply.value().at(3).toInt()-this->height()-MARGIN, this->width(),this->height()); break; } } /* use dbus to get the location of the panel */ int MainWindow::getPanelPosition(QString str) { QDBusInterface interface( "com.ukui.panel.desktop", "/", "com.ukui.panel.desktop", QDBusConnection::sessionBus() ); QDBusReply reply = interface.call("GetPanelPosition", str); return reply; } /* use the dbus to get the height of the panel */ int MainWindow::getPanelHeight(QString str) { QDBusInterface interface( "com.ukui.panel.desktop", "/", "com.ukui.panel.desktop", QDBusConnection::sessionBus() ); QDBusReply reply = interface.call("GetPanelSize", str); return reply; } void MainWindow::resizeEvent(QResizeEvent *event) { } void MainWindow::moveBottomDirect(GDrive *drive) { } void MainWindow::MainWindowShow(bool isUpdate) { this->getTransparentData(); m_dataFlashDisk->OutputInfos(); QString strTrans; strTrans = QString::number(m_transparency, 10, 2); #if (QT_VERSION < QT_VERSION_CHECK(5,7,0)) QString convertStyle = "#centralWidget{background:rgba(19,19,20,0.95);}"; #else // QString convertStyle = "#centralWidget{background:rgba(19,19,20," + strTrans + ");}"; #endif if(ui->centralWidget != NULL) { //cancel the connection between the timeout signal and main interface hiding if (insertorclick == false) { if (interfaceHideTime->isActive()) { interfaceHideTime->stop(); } } else if (!m_bIsMouseInTraIcon && !m_bIsMouseInCentral) { if (isUpdate) { if (ui->centralWidget->isHidden()) { return ; } else { if (m_dataFlashDisk->getValidInfoCount() < 1) { ui->centralWidget->hide(); return ; } } } interfaceHideTime->start(5000); } } num = 0; unsigned uDiskCount = 0; unsigned uVolumeCount = 0; QList listMainWindow = ui->centralWidget->findChildren(); for(FDClickWidget *listItem:listMainWindow) { listItem->hide(); listItem->deleteLater(); } QList listLine = ui->centralWidget->findChildren(); for(QWidget *listItem:listLine) { if(listItem->objectName() == "lineWidget") { listItem->hide(); listItem->deleteLater(); } } // only show new insert device if (insertorclick) { //Convenient interface layout for all drives map& listDriveInfo = m_dataFlashDisk->getDevInfoWithDrive(); if (!listDriveInfo.empty()) { map::iterator itDriveInfo = listDriveInfo.begin(); for ( ;itDriveInfo != listDriveInfo.end(); itDriveInfo++) { unsigned uVolumeNum = 0; bool isCanShow = (itDriveInfo->second.isCanEject || itDriveInfo->second.isCanStop || itDriveInfo->second.isRemovable); QString strDriveName = QString::fromStdString(itDriveInfo->second.strName); if (itDriveInfo->second.listVolumes.size() > 0) { uDiskCount++; } map::iterator itVolumeInfo = itDriveInfo->second.listVolumes.begin(); for ( ;itVolumeInfo != itDriveInfo->second.listVolumes.end(); itVolumeInfo++) { QString strApiName; quint64 lluTotalSize = itVolumeInfo->second.mountInfo.lluTotalSize; QString strMountUri = QString::fromStdString(itVolumeInfo->second.mountInfo.strUri); QString strDriveId = QString::fromStdString(itDriveInfo->second.strId); QString strVolumeId = QString::fromStdString(itVolumeInfo->second.strId); QString strMountId = QString::fromStdString(itVolumeInfo->second.mountInfo.strId); unsigned uVolumeType = 0; // 0:normal file volume, 1: cddata, 2:tele dev if ((itVolumeInfo->second.strId.empty() && itVolumeInfo->second.mountInfo.strId.empty()) || (!itVolumeInfo->second.isNewInsert && !itVolumeInfo->second.mountInfo.isNewInsert)) { // is not new insert device continue; } if (!itVolumeInfo->second.mountInfo.strId.empty()) { string strMountUri = itVolumeInfo->second.mountInfo.strUri; if(g_str_has_prefix(strMountUri.c_str(),"file:///")) { uVolumeType = 0; } else if (g_str_has_prefix(strMountUri.c_str(),"mtp://") || g_str_has_prefix(strMountUri.c_str(),"gphoto2://")){ uVolumeType = 2; } else if (g_str_has_prefix(strMountUri.c_str(),"burn:///")/* || g_str_has_prefix(strMountUri.c_str(),"cdda://")*/) { uVolumeType = 1; } } if (uVolumeType == 1 || uVolumeType == 2 || isCanShow) { // cd module or drive can show if (!itVolumeInfo->second.strId.empty()) { uVolumeNum++; uVolumeCount++; strApiName = QString::fromStdString(itVolumeInfo->second.strName); } else if (!itVolumeInfo->second.mountInfo.strId.empty()) { uVolumeNum++; uVolumeCount++; strApiName = QString::fromStdString(itVolumeInfo->second.mountInfo.strName); } else { continue; } } else { continue; } if (uDiskCount > 0) { if (uVolumeType == 1) { // deal with cd info if(uDiskCount == 1 || uVolumeNum != 1) { newarea(uVolumeNum, strDriveId,strVolumeId,strMountId,strDriveName, strApiName, 1, "burn:///", 1); } else { newarea(uVolumeNum, strDriveId,strVolumeId,strMountId,strDriveName, strApiName, 1, "burn:///", 2); } } else if (uVolumeType == 2) { QString telephoneName = tr("telephone device"); QByteArray strTelePhone = telephoneName.toLocal8Bit(); char *realTele = strTelePhone.data(); if(uDiskCount == 1 || uVolumeNum != 1) { newarea(uVolumeNum, strDriveId,strVolumeId,strMountId,realTele, strApiName, lluTotalSize, strMountUri,1); } else { newarea(uVolumeNum, strDriveId,strVolumeId,strMountId,realTele, strApiName, lluTotalSize, strMountUri,2); } } else { if(uDiskCount == 1 || uVolumeNum != 1) { newarea(uVolumeNum, strDriveId,strVolumeId,strMountId,strDriveName, strApiName, lluTotalSize,strMountUri,1); } else { newarea(uVolumeNum, strDriveId,strVolumeId,strMountId,strDriveName, strApiName,lluTotalSize,strMountUri,2); } } } } if (itDriveInfo->second.listVolumes.size() > 0 && uVolumeNum == 0 && uDiskCount > 0) { uDiskCount --; } } } // show volume info without drive map& listVolumeInfo = m_dataFlashDisk->getDevInfoWithVolume(); if (!listVolumeInfo.empty()) { map::iterator itVolumeInfo = listVolumeInfo.begin(); for (; itVolumeInfo != listVolumeInfo.end(); itVolumeInfo++) { QString strApiName; QString strMainName; bool isCanShow = itVolumeInfo->second.isCanEject; quint64 lluTotalSize = itVolumeInfo->second.mountInfo.lluTotalSize; QString strMountUri = QString::fromStdString(itVolumeInfo->second.mountInfo.strUri); QString strVolumeId = QString::fromStdString(itVolumeInfo->second.strId); QString strMountId = QString::fromStdString(itVolumeInfo->second.mountInfo.strId); unsigned uVolumeType = 0; // 0:normal file volume, 1: cddata, 2:tele dev if ((itVolumeInfo->second.strId.empty() && itVolumeInfo->second.mountInfo.strId.empty()) || (!itVolumeInfo->second.isNewInsert && !itVolumeInfo->second.mountInfo.isNewInsert)) { // is not new insert device continue; } if (!itVolumeInfo->second.mountInfo.strId.empty()) { string strMountUri = itVolumeInfo->second.mountInfo.strUri; if(g_str_has_prefix(strMountUri.c_str(),"file:///")) { uVolumeType = 0; } else if (g_str_has_prefix(strMountUri.c_str(),"mtp://") || g_str_has_prefix(strMountUri.c_str(),"gphoto2://")){ uVolumeType = 2; } else if (g_str_has_prefix(strMountUri.c_str(),"burn:///")/* || g_str_has_prefix(strMountUri.c_str(),"cdda://")*/) { uVolumeType = 1; } } if (uVolumeType == 1 || uVolumeType == 2 || isCanShow) { // cd module or drive can show if (!itVolumeInfo->second.strId.empty()) { uDiskCount++; uVolumeCount++; strMainName = strApiName = QString::fromStdString(itVolumeInfo->second.strName); } else if (!itVolumeInfo->second.mountInfo.strId.empty()) { uDiskCount++; uVolumeCount++; strMainName = strApiName = QString::fromStdString(itVolumeInfo->second.mountInfo.strName); } else { continue; } } else { continue; } if (uDiskCount > 0) { if (uVolumeType == 1) { // deal with cd info if(uDiskCount == 1) { newarea(1, "",strVolumeId,strMountId,strMainName, strApiName,1,"burn:///",1); } else { newarea(1, "",strVolumeId,strMountId,strMainName, strApiName,1,"burn:///",2); } } else if (uVolumeType == 2) { QString telephoneName = tr("telephone device"); QByteArray strTelePhone = telephoneName.toLocal8Bit(); char *realTele = strTelePhone.data(); if(uDiskCount == 1) { newarea(1, "",strVolumeId,strMountId,realTele, strApiName,lluTotalSize,strMountUri,1); } else { newarea(1, "",strVolumeId,strMountId,realTele, strApiName,lluTotalSize,strMountUri,2); } } else { if(uDiskCount == 1) { newarea(1, "",strVolumeId,strMountId,strMainName, strApiName,lluTotalSize,strMountUri,1); } else { newarea(1, "",strVolumeId,strMountId,strMainName, strApiName,lluTotalSize,strMountUri,2); } } } } } // show mount info without drive & volume map& listMountInfo = m_dataFlashDisk->getDevInfoWithMount(); if (!listMountInfo.empty()) { map::iterator itMountInfo = listMountInfo.begin(); for (; itMountInfo != listMountInfo.end(); itMountInfo++) { QString strApiName; QString strMainName; bool isCanShow = (itMountInfo->second.isCanUnmount || itMountInfo->second.isCanEject); quint64 lluTotalSize = itMountInfo->second.lluTotalSize; QString strMountUri = QString::fromStdString(itMountInfo->second.strUri); QString strMountId = QString::fromStdString(itMountInfo->second.strId); unsigned uMountType = 0; // 0:normal file, 1: cddata, 2:tele dev if (itMountInfo->second.strId.empty() || !itMountInfo->second.isNewInsert) { // is not new insert device continue; } if (!itMountInfo->second.strId.empty()) { string strMountUri = itMountInfo->second.strUri; if(g_str_has_prefix(strMountUri.c_str(),"file:///")) { uMountType = 0; } else if (g_str_has_prefix(strMountUri.c_str(),"mtp://") || g_str_has_prefix(strMountUri.c_str(),"gphoto2://")){ uMountType = 2; } else if (g_str_has_prefix(strMountUri.c_str(),"burn:///")/* || g_str_has_prefix(strMountUri.c_str(),"cdda://")*/) { uMountType = 1; } } else { continue; } if (uMountType == 1 || uMountType == 2 || isCanShow) { // cd module or drive can show uDiskCount++; uVolumeCount++; strMainName = strApiName = QString::fromStdString(itMountInfo->second.strName); } else { continue; } if (uDiskCount > 0) { if (uMountType == 1) { // deal with cd info if(uDiskCount == 1) { newarea(1, "","",strMountId,strMainName, strApiName,1, "burn:///", 1); } else { newarea(1, "","",strMountId,strMainName, strApiName,1, "burn:///", 2); } } else if (uMountType == 2) { QString telephoneName = tr("telephone device"); QByteArray strTelePhone = telephoneName.toLocal8Bit(); char *realTele = strTelePhone.data(); if(uDiskCount == 1) { newarea(1, "","",strMountId,realTele, strApiName,lluTotalSize,strMountUri,1); } else { newarea(1, "","",strMountId,realTele, strApiName,lluTotalSize,strMountUri,2); } } else { if(uDiskCount == 1) { newarea(1, "","",strMountId,strMainName, strApiName,lluTotalSize,strMountUri,1); } else { newarea(1, "","",strMountId,strMainName, strApiName,lluTotalSize,strMountUri,2); } } } } } } else { // show all device //Convenient interface layout for all drives map& listDriveInfo = m_dataFlashDisk->getDevInfoWithDrive(); if (!listDriveInfo.empty()) { map::iterator itDriveInfo = listDriveInfo.begin(); for ( ;itDriveInfo != listDriveInfo.end(); itDriveInfo++) { unsigned uVolumeNum = 0; bool isCanShow = (itDriveInfo->second.isCanEject || itDriveInfo->second.isCanStop || itDriveInfo->second.isRemovable); QString strDriveName = QString::fromStdString(itDriveInfo->second.strName); if (itDriveInfo->second.listVolumes.size() > 0) { uDiskCount++; } map::iterator itVolumeInfo = itDriveInfo->second.listVolumes.begin(); for ( ;itVolumeInfo != itDriveInfo->second.listVolumes.end(); itVolumeInfo++) { QString strApiName; quint64 lluTotalSize = itVolumeInfo->second.mountInfo.lluTotalSize; QString strMountUri = QString::fromStdString(itVolumeInfo->second.mountInfo.strUri); QString strDriveId = QString::fromStdString(itDriveInfo->second.strId); QString strVolumeId = QString::fromStdString(itVolumeInfo->second.strId); QString strMountId = QString::fromStdString(itVolumeInfo->second.mountInfo.strId); unsigned uVolumeType = 0; // 0:normal file volume, 1: cddata, 2:tele dev if (!itVolumeInfo->second.mountInfo.strId.empty()) { string strMountUri = itVolumeInfo->second.mountInfo.strUri; if(g_str_has_prefix(strMountUri.c_str(),"file:///")) { uVolumeType = 0; } else if (g_str_has_prefix(strMountUri.c_str(),"mtp://") || g_str_has_prefix(strMountUri.c_str(),"gphoto2://")){ uVolumeType = 2; } else if (g_str_has_prefix(strMountUri.c_str(),"burn:///")/* || g_str_has_prefix(strMountUri.c_str(),"cdda://")*/) { uVolumeType = 1; } } if (uVolumeType == 1 || uVolumeType == 2 || isCanShow) { // cd module or drive can show if (!itVolumeInfo->second.strId.empty()) { uVolumeNum++; uVolumeCount++; strApiName = QString::fromStdString(itVolumeInfo->second.strName); } else if (!itVolumeInfo->second.mountInfo.strId.empty()) { uVolumeNum++; uVolumeCount++; strApiName = QString::fromStdString(itVolumeInfo->second.mountInfo.strName); } else { continue; } } else { continue; } if (uDiskCount > 0) { if (uVolumeType == 1) { // deal with cd info if(uDiskCount == 1 || uVolumeNum != 1) { newarea(uVolumeNum, strDriveId,strVolumeId,strMountId,strDriveName, strApiName, 1, "burn:///", 1); } else { newarea(uVolumeNum, strDriveId,strVolumeId,strMountId,strDriveName, strApiName, 1, "burn:///", 2); } } else if (uVolumeType == 2) { QString telephoneName = tr("telephone device"); QByteArray strTelePhone = telephoneName.toLocal8Bit(); char *realTele = strTelePhone.data(); if(uDiskCount == 1 || uVolumeNum != 1) { newarea(uVolumeNum, strDriveId,strVolumeId,strMountId,realTele, strApiName, lluTotalSize, strMountUri,1); } else { newarea(uVolumeNum, strDriveId,strVolumeId,strMountId,realTele, strApiName, lluTotalSize, strMountUri,2); } } else { if(uDiskCount == 1 || uVolumeNum != 1) { newarea(uVolumeNum, strDriveId,strVolumeId,strMountId,strDriveName, strApiName, lluTotalSize,strMountUri,1); } else { newarea(uVolumeNum, strDriveId,strVolumeId,strMountId,strDriveName, strApiName,lluTotalSize,strMountUri,2); } } } } } } // show volume info without drive map& listVolumeInfo = m_dataFlashDisk->getDevInfoWithVolume(); if (!listVolumeInfo.empty()) { map::iterator itVolumeInfo = listVolumeInfo.begin(); for (; itVolumeInfo != listVolumeInfo.end(); itVolumeInfo++) { QString strApiName; QString strMainName; bool isCanShow = itVolumeInfo->second.isCanEject; quint64 lluTotalSize = itVolumeInfo->second.mountInfo.lluTotalSize; QString strMountUri = QString::fromStdString(itVolumeInfo->second.mountInfo.strUri); QString strVolumeId = QString::fromStdString(itVolumeInfo->second.strId); QString strMountId = QString::fromStdString(itVolumeInfo->second.mountInfo.strId); unsigned uVolumeType = 0; // 0:normal file volume, 1: cddata, 2:tele dev if (!itVolumeInfo->second.mountInfo.strId.empty()) { string strMountUri = itVolumeInfo->second.mountInfo.strUri; if(g_str_has_prefix(strMountUri.c_str(),"file:///")) { uVolumeType = 0; } else if (g_str_has_prefix(strMountUri.c_str(),"mtp://") || g_str_has_prefix(strMountUri.c_str(),"gphoto2://")){ uVolumeType = 2; } else if (g_str_has_prefix(strMountUri.c_str(),"burn:///")/* || g_str_has_prefix(strMountUri.c_str(),"cdda://")*/) { uVolumeType = 1; } } if (uVolumeType == 1 || uVolumeType == 2 || isCanShow) { // cd module or drive can show if (!itVolumeInfo->second.strId.empty()) { uDiskCount++; uVolumeCount++; strMainName = strApiName = QString::fromStdString(itVolumeInfo->second.strName); } else if (!itVolumeInfo->second.mountInfo.strId.empty()) { uDiskCount++; uVolumeCount++; strMainName = strApiName = QString::fromStdString(itVolumeInfo->second.mountInfo.strName); } else { continue; } } else { continue; } if (uDiskCount > 0) { if (uVolumeType == 1) { // deal with cd info if(uDiskCount == 1) { newarea(1, "",strVolumeId,strMountId,strMainName, strApiName,1,"burn:///",1); } else { newarea(1, "",strVolumeId,strMountId,strMainName, strApiName,1,"burn:///",2); } } else if (uVolumeType == 2) { QString telephoneName = tr("telephone device"); QByteArray strTelePhone = telephoneName.toLocal8Bit(); char *realTele = strTelePhone.data(); if(uDiskCount == 1) { newarea(1, "",strVolumeId,strMountId,realTele, strApiName,lluTotalSize,strMountUri,1); } else { newarea(1, "",strVolumeId,strMountId,realTele, strApiName,lluTotalSize,strMountUri,2); } } else { if(uDiskCount == 1) { newarea(1, "",strVolumeId,strMountId,strMainName, strApiName,lluTotalSize,strMountUri,1); } else { newarea(1, "",strVolumeId,strMountId,strMainName, strApiName,lluTotalSize,strMountUri,2); } } } } } // show mount info without drive & volume map& listMountInfo = m_dataFlashDisk->getDevInfoWithMount(); if (!listMountInfo.empty()) { map::iterator itMountInfo = listMountInfo.begin(); for (; itMountInfo != listMountInfo.end(); itMountInfo++) { QString strApiName; QString strMainName; bool isCanShow = (itMountInfo->second.isCanUnmount || itMountInfo->second.isCanEject); quint64 lluTotalSize = itMountInfo->second.lluTotalSize; QString strMountUri = QString::fromStdString(itMountInfo->second.strUri); QString strMountId = QString::fromStdString(itMountInfo->second.strId); unsigned uMountType = 0; // 0:normal file, 1: cddata, 2:tele dev if (!itMountInfo->second.strId.empty()) { string strMountUri = itMountInfo->second.strUri; if(g_str_has_prefix(strMountUri.c_str(),"file:///")) { uMountType = 0; } else if (g_str_has_prefix(strMountUri.c_str(),"mtp://") || g_str_has_prefix(strMountUri.c_str(),"gphoto2://")){ uMountType = 2; } else if (g_str_has_prefix(strMountUri.c_str(),"burn:///")/* || g_str_has_prefix(strMountUri.c_str(),"cdda://")*/) { uMountType = 1; } } else { continue; } if (uMountType == 1 || uMountType == 2 || isCanShow) { // cd module or drive can show uDiskCount++; uVolumeCount++; strMainName = strApiName = QString::fromStdString(itMountInfo->second.strName); } else { continue; } if (uDiskCount > 0) { if (uMountType == 1) { // deal with cd info if(uDiskCount == 1) { newarea(1, "","",strMountId,strMainName, strApiName,1, "burn:///", 1); } else { newarea(1, "","",strMountId,strMainName, strApiName,1, "burn:///", 2); } } else if (uMountType == 2) { QString telephoneName = tr("telephone device"); QByteArray strTelePhone = telephoneName.toLocal8Bit(); char *realTele = strTelePhone.data(); if(uDiskCount == 1) { newarea(1, "","",strMountId,realTele, strApiName,lluTotalSize,strMountUri,1); } else { newarea(1, "","",strMountId,realTele, strApiName,lluTotalSize,strMountUri,2); } } else { if(uDiskCount == 1) { newarea(1, "","",strMountId,strMainName, strApiName,lluTotalSize,strMountUri,1); } else { newarea(1, "","",strMountId,strMainName, strApiName,lluTotalSize,strMountUri,2); } } } } } } if (uDiskCount > 0) { uVolumeCount = uVolumeCount < uDiskCount ? uDiskCount : uVolumeCount; hign = uDiskCount*FLASHDISKITEM_TITLE_HEIGHT+uVolumeCount*FLASHDISKITEM_CONTENT_HEIGHT; ui->centralWidget->setFixedSize(280, hign); } else { hign = 0; ui->centralWidget->setFixedSize(0, 0); } moveBottomNoBase(); ui->centralWidget->show(); } void MainWindow::ifgetPinitMount() { int pointMountNum = 0; QFile file(tmpPath); if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { QString content = file.readLine().trimmed(); while (!file.atEnd()) { if (content.contains(".mount")) { pointMountNum += 1; } content = file.readLine().trimmed(); if(pointMountNum >= 1) { findPointMount = true; } else { findPointMount = false; } } } file.close(); } void MainWindow::onMaininterfacehide() { ui->centralWidget->hide(); this->driveVolumeNum = 0; interfaceHideTime->stop(); m_dataFlashDisk->resetAllNewState(); } void MainWindow::moveBottomNoBase() { #if 0 int position=0; int panelSize=0; if(QGSettings::isSchemaInstalled(QString("org.ukui.panel.settings").toLocal8Bit())) { QGSettings* gsetting=new QGSettings(QString("org.ukui.panel.settings").toLocal8Bit()); if(gsetting->keys().contains(QString("panelposition"))) position=gsetting->get("panelposition").toInt(); else position=0; if(gsetting->keys().contains(QString("panelsize"))) panelSize=gsetting->get("panelsize").toInt(); else panelSize=SmallPanelSize; } else { position=0; panelSize=SmallPanelSize; } int x=QApplication::primaryScreen()->geometry().x(); int y=QApplication::primaryScreen()->geometry().y(); if(position==0) ui->centralWidget->setGeometry(QRect(x + QApplication::primaryScreen()->geometry().width()-ui->centralWidget->width() - DISTANCEMEND - DISTANCEPADDING,y+ QApplication::primaryScreen()->geometry().height()-panelSize-ui->centralWidget->height() - DISTANCEPADDING,ui->centralWidget->width(),ui->centralWidget->height())); else if(position==1) ui->centralWidget->setGeometry(QRect(x + QApplication::primaryScreen()->geometry().width()-ui->centralWidget->width() - DISTANCEMEND - DISTANCEPADDING,y+ panelSize + DISTANCEPADDING,ui->centralWidget->width(),ui->centralWidget->height())); // Style::minw,Style::minh the width and the height of the interface which you want to show else if(position==2) ui->centralWidget->setGeometry(QRect(x+panelSize + DISTANCEPADDING,y + QApplication::primaryScreen()->geometry().height() - ui->centralWidget->height() - DISTANCEPADDING,ui->centralWidget->width(),ui->centralWidget->height())); else ui->centralWidget->setGeometry(QRect(x+QApplication::primaryScreen()->geometry().width()-panelSize-ui->centralWidget->width() - DISTANCEPADDING,y + QApplication::primaryScreen()->geometry().height() - ui->centralWidget->height() - DISTANCEPADDING,ui->centralWidget->width(),ui->centralWidget->height())); ui->centralWidget->repaint(); #endif // MARGIN 为到任务栏或屏幕边缘的间隔 #define MARGIN 4 QDBusInterface iface("org.ukui.panel", "/panel/position", "org.ukui.panel", QDBusConnection::sessionBus()); QDBusReply reply=iface.call("GetPrimaryScreenGeometry"); if (!iface.isValid() || !iface.isValid() || reply.value().size()<5) { qCritical() << QDBusConnection::sessionBus().lastError().message(); ui->centralWidget->setGeometry(0,0,ui->centralWidget->width(),ui->centralWidget->height()); } else { // reply获取的参数共5个,分别是 主屏可用区域的起点x坐标,主屏可用区域的起点y坐标,主屏可用区域的宽度,主屏可用区域高度,任务栏位置 QVariantList position_list=reply.value(); switch(reply.value().at(4).toInt()){ case 1: // 任务栏位于上方 ui->centralWidget->setGeometry(position_list.at(0).toInt()+position_list.at(2).toInt()-ui->centralWidget->width()-MARGIN, position_list.at(1).toInt()+MARGIN, ui->centralWidget->width(),ui->centralWidget->height()); break; // 任务栏位于左边 case 2: ui->centralWidget->setGeometry(position_list.at(0).toInt()+MARGIN, position_list.at(1).toInt()+reply.value().at(3).toInt()-ui->centralWidget->height()-MARGIN, ui->centralWidget->width(),this->height()); break; // 任务栏位于右边 case 3: ui->centralWidget->setGeometry(position_list.at(0).toInt()+position_list.at(2).toInt()-ui->centralWidget->width()-MARGIN, position_list.at(1).toInt()+reply.value().at(3).toInt()-ui->centralWidget->height()-MARGIN, ui->centralWidget->width(),ui->centralWidget->height()); break; // 任务栏位于下方 default: ui->centralWidget->setGeometry(position_list.at(0).toInt()+position_list.at(2).toInt()-ui->centralWidget->width()-MARGIN, position_list.at(1).toInt()+reply.value().at(3).toInt()-ui->centralWidget->height()-MARGIN, ui->centralWidget->width(),ui->centralWidget->height()); break; } } } /* * determine how to open the maininterface,if trigger is 0,the main interface show when we inset USB * device directly,if trigger is 1,we show main interface by clicking the systray icon. */ bool MainWindow::eventFilter(QObject *obj, QEvent *event) { #if 0 if(triggerType == 0) { if(event->type() == QEvent::Enter) { disconnect(interfaceHideTime, SIGNAL(timeout()), this, SLOT(onMaininterfacehide())); this->show(); } if(event->type() == QEvent::Leave) { connect(interfaceHideTime, SIGNAL(timeout()), this, SLOT(onMaininterfacehide())); interfaceHideTime->start(2000); } } if(triggerType == 1){} if (obj == this) { if (event->type() == QEvent::WindowDeactivate && !(this->isHidden())) { this->hide(); return true; } } if (!isActiveWindow()) { activateWindow(); } #endif return false; } // new a gsettings object to get the information of the opacity of the window void MainWindow::initTransparentState() { const QByteArray idtrans(THEME_QT_TRANS); if(QGSettings::isSchemaInstalled(idtrans)) { m_transparency_gsettings = new QGSettings(idtrans); } } // use gsettings to get the opacity void MainWindow::getTransparentData() { if (!m_transparency_gsettings) { m_transparency = 0.95; return; } QStringList keys = m_transparency_gsettings->keys(); if (keys.contains("transparency")) { m_transparency = m_transparency_gsettings->get("transparency").toDouble(); } } void MainWindow::paintEvent(QPaintEvent *event) { QPainterPath path; auto rect = this->rect(); rect.adjust(1, 1, -1, -1); path.addRoundedRect(rect, 4, 4); setProperty("blurRegion", QRegion(path.toFillPolygon().toPolygon())); QStyleOption opt; opt.init(this); QPainter p(this); QRect rectReal = this->rect(); p.setRenderHint(QPainter::Antialiasing); // 反锯齿; p.setBrush(opt.palette.color(QPalette::Base)); p.setOpacity(m_transparency); p.setPen(Qt::NoPen); p.drawRoundedRect(rectReal, 4, 4); QWidget::paintEvent(event); KWindowEffects::enableBlurBehind(this->winId(), true, QRegion(path.toFillPolygon().toPolygon())); } void MainWindow::onEjectVolumeForce(GVolume *v) { g_volume_eject_with_operation(v, G_MOUNT_UNMOUNT_FORCE, nullptr, nullptr, GAsyncReadyCallback(&MainWindow::frobnitz_force_result_func), this); } void MainWindow::AsyncUnmount(QString strMountRoot,MainWindow *p_this) { qInfo() << "dataPath:" << strMountRoot; QProcess p; p.setProgram("pkexec"); p.setArguments(QStringList() << "eject" << strMountRoot); p.start(); bool bSuccess = p.waitForFinished(); if (p_this) { p_this->ifSucess = bSuccess; } } void MainWindow::frobnitz_force_result_func(GDrive *source_object,GAsyncResult *res, MainWindow *p_this) { auto env = qgetenv("QT_QPA_PLATFORMTHEME"); gboolean success = FALSE; GError *err = nullptr; success = g_drive_eject_with_operation_finish (source_object, res, &err); if (!err) { FDDriveInfo driveInfo; char *devPath = g_drive_get_identifier(source_object,G_DRIVE_IDENTIFIER_KIND_UNIX_DEVICE); if (devPath != NULL) { driveInfo.strId = devPath; g_free(devPath); } char *strName = g_drive_get_name(source_object); if (strName) { driveInfo.strName = strName; g_free(strName); } p_this->m_eject = new ejectInterface(p_this->ui->centralWidget,QString::fromStdString(driveInfo.strName), NORMALDEVICE,QString::fromStdString(driveInfo.strId)); p_this->m_eject->show(); FlashDiskData::getInstance()->removeDriveInfo(driveInfo); if(FlashDiskData::getInstance()->getValidInfoCount() == 0) { p_this->m_systray->hide(); } } else { GList* listVolume = g_drive_get_volumes(source_object); if (listVolume) { GList* lVolume = NULL; for (lVolume = listVolume; lVolume != NULL; lVolume= lVolume->next) { GVolume* gvolume = (GVolume *)lVolume->data; GMount* gmount = g_volume_get_mount(gvolume); if (gmount) { GFile* root = g_mount_get_root(gmount); if (root) { char* strMountRoot = g_file_get_path(root); if (strMountRoot) { QString strMountPath = strMountRoot; QtConcurrent::run(&MainWindow::AsyncUnmount, strMountPath, p_this); g_free(strMountRoot); } g_object_unref(root); } g_object_unref(gmount); } } g_list_free(listVolume); listVolume = NULL; } } } void MainWindow::frobnitz_result_func(GDrive *source_object,GAsyncResult *res,MainWindow *p_this) { gboolean success = FALSE; GError *err = nullptr; success = g_drive_eject_with_operation_finish (source_object, res, &err); if (!err) { FDDriveInfo driveInfo; char *devPath = g_drive_get_identifier(source_object,G_DRIVE_IDENTIFIER_KIND_UNIX_DEVICE); if (devPath != NULL) { driveInfo.strId = devPath; g_free(devPath); } char *strName = g_drive_get_name(source_object); if (strName) { driveInfo.strName = strName; g_free(strName); } p_this->m_eject = new ejectInterface(p_this->ui->centralWidget,QString::fromStdString(driveInfo.strName), NORMALDEVICE,QString::fromStdString(driveInfo.strId)); p_this->m_eject->show(); FlashDiskData::getInstance()->removeDriveInfo(driveInfo); if(FlashDiskData::getInstance()->getValidInfoCount() == 0) { p_this->m_systray->hide(); } } else /*if(g_drive_can_stop(source_object) == true)*/ { FDDriveInfo driveInfo; char *devPath = g_drive_get_identifier(source_object,G_DRIVE_IDENTIFIER_KIND_UNIX_DEVICE); if (devPath != NULL) { driveInfo.strId = devPath; g_free(devPath); } char *strName = g_drive_get_name(source_object); if (strName) { driveInfo.strName = strName; g_free(strName); } if (p_this->chooseDialog == nullptr) { p_this->chooseDialog = new interactiveDialog(QString::fromStdString(driveInfo.strId), p_this->ui->centralWidget); } p_this->chooseDialog->show(); p_this->chooseDialog->setFocus(); p_this->connect(p_this->chooseDialog,&interactiveDialog::FORCESIG,p_this,[=]() { g_drive_eject_with_operation(source_object, G_MOUNT_UNMOUNT_FORCE, NULL, NULL, GAsyncReadyCallback(&MainWindow::frobnitz_force_result_func), p_this ); p_this->chooseDialog->close(); }); } } void MainWindow::frobnitz_normal_result_volume_eject(GVolume *source_object,GAsyncResult *res,MainWindow *p_this) { gboolean success = FALSE; GError *err = nullptr; success = g_volume_eject_with_operation_finish(source_object, res, &err); if(!err) { FDVolumeInfo volumeInfo; char *volumeId = g_volume_get_identifier(source_object,G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE); if (volumeId) { volumeInfo.strId = volumeId; g_free(volumeId); } FlashDiskData::getInstance()->removeVolumeInfo(volumeInfo); if(FlashDiskData::getInstance()->getValidInfoCount() == 0) { p_this->m_systray->hide(); } } } void MainWindow::frobnitz_force_result_unmount(GMount *source_object,GAsyncResult *res,MainWindow *p_this) { gboolean success = FALSE; GError *err = nullptr; success = g_mount_unmount_with_operation_finish(source_object,res, &err); if(!err) { FDMountInfo mountInfo; mountInfo.isCanEject = g_mount_can_eject(source_object); char *mountId = g_mount_get_uuid(source_object); if (mountId) { mountInfo.strId = mountId; g_free(mountId); } GFile *root = g_mount_get_default_location(source_object); if (root) { char *mountUri = g_file_get_uri(root); //get挂载点的uri路径 if (mountUri) { mountInfo.strUri = mountUri; g_free(mountUri); if (mountInfo.strId.empty()) { mountInfo.strId = mountInfo.strUri; } } g_object_unref(root); } FlashDiskData::getInstance()->removeMountInfo(mountInfo); if(FlashDiskData::getInstance()->getValidInfoCount() == 0) { p_this->m_systray->hide(); } } } void MainWindow::onClickedEject(EjectDeviceInfo eDeviceInfo) { m_curEjectDeviceInfo = eDeviceInfo; m_curEjectDeviceInfo.pVoid = this; m_curEjectDeviceInfo.uFlag = G_MOUNT_UNMOUNT_NONE; doRealEject(&m_curEjectDeviceInfo, G_MOUNT_UNMOUNT_NONE); } bool MainWindow::onDeviceErrored(GDrive* drive) { g_return_val_if_fail(G_IS_DRIVE(drive), false); g_autofree char* device = g_drive_get_identifier (drive, G_DRIVE_IDENTIFIER_KIND_UNIX_DEVICE); g_return_val_if_fail(device && strstr(device, "/dev/sd"), false); g_return_val_if_fail (DeviceOperation::getDriveSize(drive) > 0, false); GList* volumes = g_drive_get_volumes(drive); if (!volumes && !mRepairDialog.contains(device)) { RepairDialogBox* b = new RepairDialogBox(drive); b->connect(b, &RepairDialogBox::repairOK, this, [=] (RepairDialogBox* d) { if (mRepairDialog.contains(d->getDeviceName())) { mRepairDialog.remove(d->getDeviceName()); } }); mRepairDialog[device] = b; b->show(); } else { for (auto v = volumes; nullptr != v; v = v->next) { GVolume* vv = G_VOLUME(v->data); g_autofree char* volumeName = g_volume_get_identifier (vv, G_DRIVE_IDENTIFIER_KIND_UNIX_DEVICE); g_autoptr(GMount) m = g_volume_get_mount(vv); if (!m) { if (volumeName && !mRepairDialog.contains(volumeName)) { RepairDialogBox* b = new RepairDialogBox(vv); b->connect(b, &RepairDialogBox::remountDevice, this, &MainWindow::remountVolume); b->connect(b, &RepairDialogBox::repairOK, this, [=] (RepairDialogBox* d) { if (mRepairDialog.contains(d->getDeviceName())) { mRepairDialog.remove(d->getDeviceName()); } }); mRepairDialog[volumeName] = b; b->show(); } } } g_list_free_full(volumes, g_object_unref); } return true; } void MainWindow::onMountVolume(GVolume* v) { g_volume_mount(v, G_MOUNT_MOUNT_NONE, nullptr, nullptr, GAsyncReadyCallback(frobnitz_result_func_volume), this); } bool MainWindow::doRealEject(EjectDeviceInfo* peDeviceInfo, GMountUnmountFlags flag) { // find the device's drive & volume & mount if (!peDeviceInfo || !peDeviceInfo->pVoid) { return false; } GList *lDrive = NULL; GList *lVolume = NULL; GList *lMount = NULL; GList *current_drive_list = NULL; GList *current_volume_list = NULL; GList *current_mount_list = NULL; GDrive* devDrive = NULL; GVolume* devVolume = NULL; GMount* devMount = NULL; unsigned uVolumeSize = 0; bool isDone = false; //about drive GVolumeMonitor *g_volume_monitor = g_volume_monitor_get(); if (!peDeviceInfo->strDriveId.isEmpty()) { current_drive_list = g_volume_monitor_get_connected_drives(g_volume_monitor); for (lDrive = current_drive_list; lDrive != NULL; lDrive = lDrive->next) { GDrive *gdrive = (GDrive *)lDrive->data; char *devPath = g_drive_get_identifier(gdrive,G_DRIVE_IDENTIFIER_KIND_UNIX_DEVICE); if (devPath != NULL) { if(peDeviceInfo->strDriveId == devPath) { devDrive = gdrive; current_volume_list = g_drive_get_volumes(gdrive); if (current_volume_list) { uVolumeSize = g_list_length(current_volume_list); for(lVolume = current_volume_list; lVolume != NULL; lVolume = lVolume->next){ //遍历驱动器上的所有卷设备 GVolume* volume = (GVolume *)lVolume->data; char *volumeId = g_volume_get_identifier(volume,G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE); if (volumeId) { if (peDeviceInfo->strVolumeId != volumeId) { g_free(volumeId); continue; } g_free(volumeId); } else { continue ; } devVolume = volume; break; } } } g_free(devPath); } } if (devDrive != NULL) { if (devDrive != NULL) { if (peDeviceInfo->strMountUri.isEmpty()) { g_drive_eject_with_operation(devDrive, flag, NULL, NULL, GAsyncReadyCallback(&MainWindow::frobnitz_result_func), peDeviceInfo->pVoid); isDone = true; } else { if (g_drive_can_eject(devDrive)){//for udisk or DVD. g_drive_eject_with_operation(devDrive, flag, NULL, NULL, GAsyncReadyCallback(&MainWindow::frobnitz_result_func), peDeviceInfo->pVoid); isDone = true; #if 0 GFile *file = g_file_new_for_uri(peDeviceInfo->strMountUri.toUtf8().constData()); if (file) { g_file_eject_mountable_with_operation(file, flag, nullptr, nullptr, GAsyncReadyCallback(fileEjectMountableCB), peDeviceInfo); g_object_unref(file); isDone = true; } #endif } else if(g_drive_can_stop(devDrive) || g_drive_is_removable(devDrive)){//for mobile harddisk. g_drive_stop(devDrive, flag, NULL, NULL, GAsyncReadyCallback(driveStopCb), peDeviceInfo); isDone = true; } } } } if (current_volume_list) { g_list_free(current_volume_list); current_volume_list = NULL; } if (current_drive_list) { g_list_free(current_drive_list); current_drive_list = NULL; } } //about volume not associated with a drive if (!isDone && !peDeviceInfo->strVolumeId.isEmpty()) { current_volume_list = g_volume_monitor_get_volumes(g_volume_monitor); if (current_volume_list) { for (lVolume = current_volume_list; lVolume != NULL; lVolume = lVolume->next) { GVolume *volume = (GVolume *)lVolume->data; GDrive *gdrive = g_volume_get_drive(volume); if (!gdrive) { char *volumeId = g_volume_get_identifier(volume,G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE); if (volumeId) { if (peDeviceInfo->strVolumeId != volumeId) { g_free(volumeId); continue; } g_free(volumeId); } else { continue ; } devVolume = volume; break; } else { g_object_unref(gdrive); } } } if (devVolume != NULL) { GMount* pCurMount = g_volume_get_mount(devVolume); if (pCurMount) { g_mount_unmount_with_operation(pCurMount, flag, NULL, NULL, GAsyncReadyCallback(&MainWindow::frobnitz_force_result_unmount), peDeviceInfo->pVoid); g_object_unref(pCurMount); isDone = true; } } if (current_volume_list) { g_list_free(current_volume_list); current_volume_list = NULL; } } //about mount not associated with a volume if (!isDone && !peDeviceInfo->strMountId.isEmpty()) { current_mount_list = g_volume_monitor_get_mounts(g_volume_monitor); if (current_mount_list) { for (lMount = current_mount_list; lMount != NULL; lMount = lMount->next) { GMount *gmount = (GMount *)lMount->data; GVolume *gvolume = g_mount_get_volume(gmount); if (!gvolume) { QString strId = ""; char *mountId = g_mount_get_uuid(gmount); if (mountId) { strId = mountId; g_free(mountId); } // get mount uri GFile *root = g_mount_get_default_location(gmount); if (root) { char *mountUri = g_file_get_uri(root); //get挂载点的uri路径 if (mountUri) { if (strId.isEmpty()) { strId = mountUri; } g_free(mountUri); } g_object_unref(root); } if (peDeviceInfo->strMountId == strId) { devMount = gmount; break; } } else { g_object_unref(gvolume); } } if (devMount != NULL) { g_mount_unmount_with_operation(devMount, flag, NULL, NULL, GAsyncReadyCallback(&MainWindow::frobnitz_force_result_unmount), peDeviceInfo->pVoid); isDone = true; } g_list_free(current_mount_list); current_mount_list = NULL; } } if (!isDone) { FDMountInfo mountInfo; FDVolumeInfo volumeInfo; FDDriveInfo driveInfo; mountInfo.strId = peDeviceInfo->strMountId.toStdString(); m_dataFlashDisk->removeMountInfo(mountInfo); volumeInfo.strId = peDeviceInfo->strVolumeId.toStdString(); m_dataFlashDisk->removeVolumeInfo(volumeInfo); driveInfo.strId = peDeviceInfo->strDriveId.toStdString(); m_dataFlashDisk->removeDriveInfo(driveInfo); if(m_dataFlashDisk->getValidInfoCount() == 0) { m_systray->hide(); } } ui->centralWidget->hide(); return true; } GAsyncReadyCallback MainWindow::fileEjectMountableCB(GFile *file, GAsyncResult *res, EjectDeviceInfo *peDeviceInfo) { gboolean success = FALSE; GError *err = nullptr; success = g_file_eject_mountable_with_operation_finish(file, res, &err); if (!err) { FDDriveInfo driveInfo; driveInfo.strId = peDeviceInfo->strDriveId.toStdString(); driveInfo.strName = peDeviceInfo->strDriveName.toStdString(); MainWindow* pThis = (MainWindow*)(peDeviceInfo->pVoid); pThis->m_eject = new ejectInterface(pThis->ui->centralWidget,QString::fromStdString(driveInfo.strName), NORMALDEVICE,QString::fromStdString(driveInfo.strId)); pThis->m_eject->show(); FlashDiskData::getInstance()->removeDriveInfo(driveInfo); if(FlashDiskData::getInstance()->getValidInfoCount() == 0) { pThis->m_systray->hide(); } } else /*if(g_drive_can_stop(source_object) == true)*/ { if (peDeviceInfo->uFlag != G_MOUNT_UNMOUNT_FORCE) { FDDriveInfo driveInfo; driveInfo.strId = peDeviceInfo->strDriveId.toStdString(); driveInfo.strName = peDeviceInfo->strDriveName.toStdString(); MainWindow* pThis = (MainWindow*)(peDeviceInfo->pVoid); if (pThis->chooseDialog == nullptr) { pThis->chooseDialog = new interactiveDialog(QString::fromStdString(driveInfo.strId), pThis->ui->centralWidget); } pThis->chooseDialog->show(); pThis->chooseDialog->setFocus(); pThis->connect(pThis->chooseDialog,&interactiveDialog::FORCESIG,pThis,[=]() { pThis->chooseDialog->close(); peDeviceInfo->uFlag = G_MOUNT_UNMOUNT_FORCE; pThis->doRealEject(peDeviceInfo, G_MOUNT_UNMOUNT_FORCE); }); } } return nullptr; } void MainWindow::driveStopCb(GObject* object, GAsyncResult* res, EjectDeviceInfo *peDeviceInfo) { gboolean success = FALSE; GError *err = nullptr; success = g_drive_stop_finish(G_DRIVE(object), res, &err); qInfo() << "driveStopCb:" << success; if (success || !err || (G_IO_ERROR_FAILED_HANDLED == err->code)) { FDDriveInfo driveInfo; driveInfo.strId = peDeviceInfo->strDriveId.toStdString(); driveInfo.strName = peDeviceInfo->strDriveName.toStdString(); MainWindow* pThis = (MainWindow*)(peDeviceInfo->pVoid); pThis->m_eject = new ejectInterface(pThis->ui->centralWidget,QString::fromStdString(driveInfo.strName), NORMALDEVICE,QString::fromStdString(driveInfo.strId)); pThis->m_eject->show(); FlashDiskData::getInstance()->removeDriveInfo(driveInfo); if(FlashDiskData::getInstance()->getValidInfoCount() == 0) { pThis->m_systray->hide(); } } else { if (peDeviceInfo->uFlag != G_MOUNT_UNMOUNT_FORCE) { FDDriveInfo driveInfo; driveInfo.strId = peDeviceInfo->strDriveId.toStdString(); driveInfo.strName = peDeviceInfo->strDriveName.toStdString(); MainWindow* pThis = (MainWindow*)(peDeviceInfo->pVoid); if (pThis->chooseDialog == nullptr) { pThis->chooseDialog = new interactiveDialog(QString::fromStdString(driveInfo.strId), pThis->ui->centralWidget); } pThis->chooseDialog->show(); pThis->chooseDialog->setFocus(); pThis->connect(pThis->chooseDialog,&interactiveDialog::FORCESIG,pThis,[=]() { pThis->chooseDialog->close(); peDeviceInfo->uFlag = G_MOUNT_UNMOUNT_FORCE; pThis->doRealEject(peDeviceInfo, G_MOUNT_UNMOUNT_FORCE); }); } } } void MainWindow::onRemountVolume(FDVolumeInfo volumeInfo) { if (volumeInfo.strId.empty()) { return; } if (!(g_str_has_prefix(volumeInfo.strId.c_str(),"/dev/bus") || g_str_has_prefix(volumeInfo.strId.c_str(),"/dev/sd"))) { return; } qInfo() << "volumeInfo.strId:" << volumeInfo.strId.c_str(); GList *lDrive = NULL; GList *lVolume = NULL; GList *current_drive_list = NULL; GList *current_volume_list = NULL; GDrive* devDrive = NULL; GVolume* devVolume = NULL; bool isDone = false; //about drive GVolumeMonitor *g_volume_monitor = g_volume_monitor_get(); current_drive_list = g_volume_monitor_get_connected_drives(g_volume_monitor); for (lDrive = current_drive_list; lDrive != NULL; lDrive = lDrive->next) { GDrive *gdrive = (GDrive *)lDrive->data; char *devPath = g_drive_get_identifier(gdrive,G_DRIVE_IDENTIFIER_KIND_UNIX_DEVICE); if (devPath != NULL) { devDrive = gdrive; current_volume_list = g_drive_get_volumes(gdrive); if (current_volume_list) { for(lVolume = current_volume_list; lVolume != NULL; lVolume = lVolume->next){ //遍历驱动器上的所有卷设备 GVolume* volume = (GVolume *)lVolume->data; char *volumeId = g_volume_get_identifier(volume,G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE); if (volumeId) { if (volumeInfo.strId != volumeId) { g_free(volumeId); continue; } g_free(volumeId); } else { continue ; } devVolume = volume; break; } } g_free(devPath); } } if (devVolume != NULL) { isDone = true; GMount* pCurMount = g_volume_get_mount(devVolume); if (pCurMount) { g_object_unref(pCurMount); } else { volumeInfo.isCanMount = g_volume_can_mount(devVolume); qInfo()<<"Volume canmount:"<get(IFAUTOLOAD).toBool(); if(ifsettings->get(IFAUTOLOAD).toBool()) { g_volume_mount(devVolume, G_MOUNT_MOUNT_NONE, nullptr, nullptr, GAsyncReadyCallback(frobnitz_result_func_volume), this); } } } if (current_volume_list) { g_list_free(current_volume_list); current_volume_list = NULL; } if (current_drive_list) { g_list_free(current_drive_list); current_drive_list = NULL; } //about volume not associated with a drive if (!isDone) { current_volume_list = g_volume_monitor_get_volumes(g_volume_monitor); if (current_volume_list) { for (lVolume = current_volume_list; lVolume != NULL; lVolume = lVolume->next) { GVolume *volume = (GVolume *)lVolume->data; GDrive *gdrive = g_volume_get_drive(volume); if (!gdrive) { char *volumeId = g_volume_get_identifier(volume,G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE); if (volumeId) { if (volumeInfo.strId != volumeId) { g_free(volumeId); continue; } g_free(volumeId); } else { continue ; } devVolume = volume; break; } else { g_object_unref(gdrive); } } } if (devVolume != NULL) { isDone = true; GMount* pCurMount = g_volume_get_mount(devVolume); if (pCurMount) { g_object_unref(pCurMount); } else { volumeInfo.isCanMount = g_volume_can_mount(devVolume); qInfo()<<"Volume canmount:"<get(IFAUTOLOAD).toBool(); if(ifsettings->get(IFAUTOLOAD).toBool()) { g_volume_mount(devVolume, G_MOUNT_MOUNT_NONE, nullptr, nullptr, GAsyncReadyCallback(frobnitz_result_func_volume), this); } } } if (current_volume_list) { g_list_free(current_volume_list); current_volume_list = NULL; } } } void MainWindow::onCheckDriveValid(FDDriveInfo driveInfo) { if (driveInfo.strId.empty()) { return; } qInfo() << "driveInfo.strId:" << driveInfo.strId.c_str(); if(!this->isSystemRootDev(driveInfo.strId.c_str()) && (driveInfo.isCanEject || driveInfo.isCanStop || driveInfo.isRemovable)) { if(g_str_has_prefix(driveInfo.strId.c_str(),"/dev/sr") || g_str_has_prefix(driveInfo.strId.c_str(),"/dev/bus") || g_str_has_prefix(driveInfo.strId.c_str(),"/dev/sd") || g_str_has_prefix(driveInfo.strId.c_str(),"/dev/mmcblk")) { GList *lDrive = NULL; GList *current_drive_list = NULL; GDrive* devDrive = NULL; //about drive GVolumeMonitor *g_volume_monitor = g_volume_monitor_get(); current_drive_list = g_volume_monitor_get_connected_drives(g_volume_monitor); for (lDrive = current_drive_list; lDrive != NULL; lDrive = lDrive->next) { GDrive *gdrive = (GDrive *)lDrive->data; char *devPath = g_drive_get_identifier(gdrive,G_DRIVE_IDENTIFIER_KIND_UNIX_DEVICE); if (devPath != NULL) { string strId = devPath; if (strId == driveInfo.strId) { devDrive = gdrive; g_free(devPath); break; } g_free(devPath); } } if (devDrive != NULL) { if (!g_drive_has_volumes(devDrive)) { Q_EMIT this->deviceError(devDrive); } } if (current_drive_list) { g_list_free(current_drive_list); current_drive_list = NULL; } } } } bool MainWindow::getDataCDRomCapacity(QString strDevId, quint64 &totalCapacity) { if (!strDevId.startsWith("/dev/sr")) { return false; } quint64 uTotalCapacity = 0; DataCDROM *cdrom = new DataCDROM(strDevId); if (cdrom) { cdrom->getCDROMInfo(); uTotalCapacity = cdrom->getCDROMCapacity(); delete cdrom; cdrom = nullptr; } if (uTotalCapacity > 0) { totalCapacity = uTotalCapacity; return true; } else { return false; } } void MainWindow::getDriveIconsInfo(GDrive* drive, FDDriveInfo& driveInfo) { GIcon *g_icon = g_drive_get_icon(drive); if (g_icon) { if (G_IS_THEMED_ICON(g_icon)) { const gchar* const* icon_names = g_themed_icon_get_names(G_THEMED_ICON (g_icon)); if (icon_names) { driveInfo.strIconPath = *icon_names; } } g_object_unref(g_icon); } } void MainWindow::getVolumeIconsInfo(GVolume* volume, FDVolumeInfo& volumeInfo) { GIcon *g_icon = g_volume_get_icon(volume); if (g_icon) { if (G_IS_THEMED_ICON(g_icon)) { const gchar* const* icon_names = g_themed_icon_get_names(G_THEMED_ICON (g_icon)); if (icon_names) { volumeInfo.strIconPath = *icon_names; } } g_object_unref(g_icon); } } void MainWindow::getMountIconsInfo(GMount* mount, FDMountInfo& mountInfo) { GIcon *g_icon = g_mount_get_icon(mount); if (g_icon) { if (G_IS_ICON(g_icon)) { if (G_IS_THEMED_ICON(g_icon)) { const gchar* const* icon_names = g_themed_icon_get_names(G_THEMED_ICON (g_icon)); if (icon_names) { mountInfo.strIconPath = *icon_names; } } else { // if it's a bootable-media,maybe we can get the icon from the mount directory. char *bootableIcon = g_icon_to_string(g_icon); if(bootableIcon) { mountInfo.strIconPath = bootableIcon; g_free(bootableIcon); } } } g_object_unref(g_icon); } } ukui-panel-3.0.6.4/ukui-flash-disk/device-manager.cpp0000644000175000017500000000402514203402514020723 0ustar fengfeng/* * Copyright (C) 2021 KylinSoft Co., Ltd. * * Authors: * Ding Jing dingjing@kylinos.cn * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see (pThis); Q_UNUSED(dm); Q_UNUSED(monitor); } void DeviceManager::drive_disconnected_callback(GVolumeMonitor* monitor, GDrive* drive, gpointer pThis) { g_return_if_fail(drive); g_return_if_fail(pThis); #if 0 DeviceManager* dm = static_cast(pThis); g_autofree gchar* devName = g_drive_get_identifier(drive, G_DRIVE_IDENTIFIER_KIND_UNIX_DEVICE); if (nullptr != devName) { Q_EMIT dm->driveDisconnected(devName); } #endif Q_UNUSED(monitor); } ukui-panel-3.0.6.4/ukui-flash-disk/gpartedinterface.cpp0000644000175000017500000001200014203402514021353 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see gpartedInterface::gpartedInterface(QWidget *parent):QWidget(parent) { this->setFixedSize(300,86); this->setWindowFlags(Qt::FramelessWindowHint | Qt::Popup); this->setAttribute(Qt::WA_TranslucentBackground); initWidgets(); moveChooseDialogRight(); initTransparentState(); getTransparentData(); } void gpartedInterface::initTransparentState() { const QByteArray idtrans(THEME_QT_TRANS); if(QGSettings::isSchemaInstalled(idtrans)) { m_transparency_gsettings = new QGSettings(idtrans); } } void gpartedInterface::getTransparentData() { if (!m_transparency_gsettings) { m_transparency = 0.95; return; } QStringList keys = m_transparency_gsettings->keys(); if (keys.contains("transparency")) { m_transparency = m_transparency_gsettings->get("transparency").toDouble(); } } void gpartedInterface::initWidgets() { noticeLabel = new QLabel(this); noticeLabel->setText(tr("gparted has started,can not eject")); okButton = new QPushButton(tr("ok")); notice_H_BoxLayout = new QHBoxLayout(); main_V_BoxLayout = new QVBoxLayout(); button_H_BoxLayout = new QHBoxLayout(); notice_H_BoxLayout->addWidget(noticeLabel); button_H_BoxLayout->addWidget(okButton,1,Qt::AlignRight); main_V_BoxLayout->addLayout(notice_H_BoxLayout); main_V_BoxLayout->addLayout(button_H_BoxLayout); this->setLayout(main_V_BoxLayout); connect(okButton,SIGNAL(clicked()),this,SLOT(close())); } void gpartedInterface::moveChooseDialogRight() { int position=0; int panelSize=0; if(QGSettings::isSchemaInstalled(QString("org.ukui.panel.settings").toLocal8Bit())) { QGSettings* gsetting=new QGSettings(QString("org.ukui.panel.settings").toLocal8Bit()); if(gsetting->keys().contains(QString("panelposition"))) position=gsetting->get("panelposition").toInt(); else position=0; if(gsetting->keys().contains(QString("panelsize"))) panelSize=gsetting->get("panelsize").toInt(); else panelSize=SmallPanelSize; } else { position=0; panelSize=SmallPanelSize; } int x=QApplication::primaryScreen()->geometry().x(); int y=QApplication::primaryScreen()->geometry().y(); qDebug()<<"QApplication::primaryScreen()->geometry().x();"<geometry().x(); qDebug()<<"QApplication::primaryScreen()->geometry().y();"<geometry().y(); if(position==0) this->setGeometry(QRect(x + QApplication::primaryScreen()->geometry().width()-this->width() - DISTANCEPADDING - DISTANCEMEND,y+QApplication::primaryScreen()->geometry().height()-panelSize-this->height() - DISTANCEPADDING,this->width(),this->height())); else if(position==1) this->setGeometry(QRect(x + QApplication::primaryScreen()->geometry().width()-this->width() - DISTANCEPADDING - DISTANCEMEND,y+panelSize + DISTANCEPADDING,this->width(),this->height())); // Style::minw,Style::minh the width and the height of the interface which you want to show else if(position==2) this->setGeometry(QRect(x+panelSize + DISTANCEPADDING,y + QApplication::primaryScreen()->geometry().height() - this->height() - DISTANCEPADDING,this->width(),this->height())); else this->setGeometry(QRect(x+QApplication::primaryScreen()->geometry().width()-panelSize-this->width() - DISTANCEPADDING,y + QApplication::primaryScreen()->geometry().height() - this->height() - DISTANCEPADDING,this->width(),this->height())); } gpartedInterface::~gpartedInterface() { } void gpartedInterface::paintEvent(QPaintEvent *event) { QPainterPath path; auto rect = this->rect(); rect.adjust(1, 1, -1, -1); path.addRoundedRect(rect, 6, 6); setProperty("blurRegion", QRegion(path.toFillPolygon().toPolygon())); QStyleOption opt; opt.init(this); QPainter p(this); QRect rectReal = this->rect(); p.setRenderHint(QPainter::Antialiasing); // 反锯齿; p.setBrush(opt.palette.color(QPalette::Base)); p.setOpacity(m_transparency); p.setPen(Qt::NoPen); p.drawRoundedRect(rectReal, 6, 6); QWidget::paintEvent(event); KWindowEffects::enableBlurBehind(this->winId(), true, QRegion(path.toFillPolygon().toPolygon())); } ukui-panel-3.0.6.4/ukui-flash-disk/ejectInterface.cpp0000644000175000017500000002473514203402514021001 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include "flashdiskdata.h" ejectInterface::ejectInterface(QWidget *parent,QString mount_name,int deviceType,QString strDevId) : QWidget(parent),eject_image_label(nullptr),show_text_label(nullptr), mount_name_label(nullptr) { initFontSetting(); getFontSize(); //interface layout this->setWindowFlags(Qt::FramelessWindowHint | Qt::Popup); EjectScreen = qApp->primaryScreen(); eject_image_label = new QLabel(this); eject_image_label->setFixedSize(24,24); //QPixmap pixmap("kylin-media-removable-symbolic"); QString strNoraml = ""; QString strIcon = FlashDiskData::getInstance()->getVolumeIcon(strDevId); eject_image_icon = QIcon::fromTheme(strIcon); strNoraml = mount_name; if (eject_image_icon.isNull()) { eject_image_icon = QIcon::fromTheme("kylin-media-removable-symbolic"); } QPixmap pixmap = eject_image_icon.pixmap(QSize(24, 24)); eject_image_label->setPixmap(pixmap); //add it to show the eject button show_text_label = new QLabel(this); show_text_label->setFixedSize(192, 36); show_text_label->setFont(QFont("Noto Sans CJK SC",fontSize)); show_text_label->setAlignment(Qt::AlignHCenter); QString normalShow = getElidedText(show_text_label->font(),strNoraml,192); //add the text of the eject interface show_text_label->setText(normalShow); if (strNoraml != normalShow) { show_text_label->setToolTip(strNoraml); } ejectinterface_h_BoxLayout = new QHBoxLayout(); ejectinterface_h_BoxLayout->setContentsMargins(0,0,0,0); ejectinterface_h_BoxLayout->setSpacing(8); ejectinterface_h_BoxLayout->addWidget(eject_image_label,0,Qt::AlignLeft|Qt::AlignTop); ejectinterface_h_BoxLayout->addWidget(show_text_label,0,Qt::AlignHCenter|Qt::AlignTop); QHBoxLayout *ejectTipLayout = new QHBoxLayout(); ejectTipLayout->setContentsMargins(0,0,0,0); ejectTipLayout->setSpacing(0); QLabel *ejectTip = new QLabel(); ejectTip->setText(tr("Storage device can be safely unplugged")); ejectTip->setAlignment(Qt::AlignHCenter|Qt::AlignTop); ejectTip->setWordWrap(true); ejectTipLayout->addWidget(ejectTip,0,Qt::AlignHCenter|Qt::AlignTop); main_V_BoxLayput = new QVBoxLayout; main_V_BoxLayput->setContentsMargins(8,8,8,8); main_V_BoxLayput->setSpacing(0); main_V_BoxLayput->addLayout(ejectinterface_h_BoxLayout); main_V_BoxLayput->addLayout(ejectTipLayout); main_V_BoxLayput->addStretch(); QString strTipShow = getElidedText(ejectTip->font(),ejectTip->text(),224); if (strTipShow != ejectTip->text()) { this->setFixedSize(240,120); } else { this->setFixedSize(240,90); } this->setWindowFlags(Qt::FramelessWindowHint | Qt::Popup); this->setAttribute(Qt::WA_TranslucentBackground);//设置窗口背景透明 this->setAttribute(Qt::WA_DeleteOnClose); //设置窗口关闭时自动销毁 this->setLayout(main_V_BoxLayput); //set the main signal-slot function to complete the eject interface to let it disappear automatically interfaceHideTime = new QTimer(this); interfaceHideTime->setTimerType(Qt::PreciseTimer); connect(interfaceHideTime, SIGNAL(timeout()), this, SLOT(on_interface_hide())); interfaceHideTime->start(1000); moveEjectInterfaceRight(); initTransparentState(); this->getTransparentData(); } ejectInterface::~ejectInterface() { if (m_transparency_gsettings) { delete m_transparency_gsettings; m_transparency_gsettings = nullptr; } if (fontSettings) { delete fontSettings; fontSettings = nullptr; } } //If the fillet does not take effect void ejectInterface::paintEvent(QPaintEvent *event) { QPainterPath path; auto rect = this->rect(); rect.adjust(1, 1, -1, -1); path.addRoundedRect(rect, 6, 6); setProperty("blurRegion", QRegion(path.toFillPolygon().toPolygon())); QStyleOption opt; opt.init(this); QPainter p(this); QRect rectReal = this->rect(); p.setRenderHint(QPainter::Antialiasing); // 反锯齿; p.setBrush(opt.palette.color(QPalette::Base)); p.setOpacity(m_transparency); p.setPen(Qt::NoPen); p.drawRoundedRect(rectReal, 6, 6); QWidget::paintEvent(event); KWindowEffects::enableBlurBehind(this->winId(), true, QRegion(path.toFillPolygon().toPolygon())); } //slot function to hide eject interface void ejectInterface::on_interface_hide() { this->hide(); this->deleteLater(); } //set the location of the eject interface void ejectInterface::moveEjectInterfaceRight() { // if(EjectScreen->availableGeometry().x() == EjectScreen->availableGeometry().y() && EjectScreen->availableSize().height() < EjectScreen->size().height()) // { // qDebug()<<"the position of panel is down"; // this->move(EjectScreen->availableGeometry().x() + EjectScreen->size().width() - // this->width() - DistanceToPanel,EjectScreen->availableGeometry().y() + // EjectScreen->availableSize().height() - this->height() - DistanceToPanel); // } // if(EjectScreen->availableGeometry().x() < EjectScreen->availableGeometry().y() && EjectScreen->availableSize().height() < EjectScreen->size().height()) // { // qDebug()<<"this position of panel is up"; // this->move(EjectScreen->availableGeometry().x() + EjectScreen->size().width() - // this->width() - DistanceToPanel,EjectScreen->availableGeometry().y()); // } // if(EjectScreen->availableGeometry().x() > EjectScreen->availableGeometry().y() && EjectScreen->availableSize().width() < EjectScreen->size().width()) // { // qDebug()<<"this position of panel is left"; // this->move(EjectScreen->availableGeometry().x() + DistanceToPanel,EjectScreen->availableGeometry().y() // + EjectScreen->availableSize().height() - this->height()); // } // if(EjectScreen->availableGeometry().x() == EjectScreen->availableGeometry().y() && EjectScreen->availableSize().width() < EjectScreen->size().width()) // { // qDebug()<<"this position of panel is right"; // this->move(EjectScreen->availableGeometry().x() + EjectScreen->availableSize().width() - // DistanceToPanel - this->width(),EjectScreen->availableGeometry().y() + // EjectScreen->availableSize().height() - (this->height())*(DistanceToPanel - 1)); // } //show the ejectinterface by primaryscreen() int position=0; int panelSize=0; if(QGSettings::isSchemaInstalled(QString("org.ukui.panel.settings").toLocal8Bit())) { QGSettings* gsetting=new QGSettings(QString("org.ukui.panel.settings").toLocal8Bit()); if(gsetting->keys().contains(QString("panelposition"))) position=gsetting->get("panelposition").toInt(); else position=0; if(gsetting->keys().contains(QString("panelsize"))) panelSize=gsetting->get("panelsize").toInt(); else panelSize=SmallPanelSize; } else { position=0; panelSize=SmallPanelSize; } int x=QApplication::primaryScreen()->geometry().x(); int y=QApplication::primaryScreen()->geometry().y(); if(position==0) this->setGeometry(QRect(x + QApplication::primaryScreen()->geometry().width()-this->width(),y+QApplication::primaryScreen()->geometry().height()-panelSize-this->height(),this->width(),this->height())); else if(position==1) this->setGeometry(QRect(x + QApplication::primaryScreen()->geometry().width()-this->width(),y+panelSize,this->width(),this->height())); // Style::minw,Style::minh the width and the height of the interface which you want to show else if(position==2) this->setGeometry(QRect(x+panelSize,y + QApplication::primaryScreen()->geometry().height() - this->height(),this->width(),this->height())); else this->setGeometry(QRect(x+QApplication::primaryScreen()->geometry().width()-panelSize-this->width(),y + QApplication::primaryScreen()->geometry().height() - this->height(),this->width(),this->height())); } int ejectInterface::getPanelPosition(QString str) { QDBusInterface interface( "com.ukui.panel.desktop", "/", "com.ukui.panel.desktop", QDBusConnection::sessionBus() ); QDBusReply reply = interface.call("GetPanelPosition", str); return reply; } /* use the dbus to get the height of the panel */ int ejectInterface::getPanelHeight(QString str) { QDBusInterface interface( "com.ukui.panel.desktop", "/", "com.ukui.panel.desktop", QDBusConnection::sessionBus() ); QDBusReply reply = interface.call("GetPanelSize", str); return reply; } void ejectInterface::initTransparentState() { const QByteArray idtrans(THEME_QT_TRANS); if(QGSettings::isSchemaInstalled(idtrans)) { m_transparency_gsettings = new QGSettings(idtrans); } } void ejectInterface::getTransparentData() { if (!m_transparency_gsettings) { m_transparency = 0.95; return; } QStringList keys = m_transparency_gsettings->keys(); if (keys.contains("transparency")) { m_transparency = m_transparency_gsettings->get("transparency").toDouble(); } } void ejectInterface::initFontSetting() { const QByteArray id(THEME_QT_SCHEMA); if(QGSettings::isSchemaInstalled(id)) { fontSettings = new QGSettings(id); } } void ejectInterface::getFontSize() { if (!fontSettings) { fontSize = 11; return; } QStringList keys = fontSettings->keys(); if (keys.contains("systemFont") || keys.contains("systemFontSize")) { fontSize = fontSettings->get("system-font").toInt(); } } ukui-panel-3.0.6.4/ukui-flash-disk/UnionVariable.h0000644000175000017500000000250614203402514020261 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include #include #include QList *findGMountList(); QList *findTeleGMountList(); QList *findGVolumeList(); QList *findTeleGVolumeList(); QList *findGDriveList(); QString getElidedText(QFont font, QString str, int MaxWidth); QString transcodeForGbkCode(QByteArray gbkName, QString &volumeName); void handleVolumeLabelForFat32Me(QString &volumeName,const QString &unixDevcieName); //int m_system(char *cmd); #endif ukui-panel-3.0.6.4/ukui-flash-disk/ukui-flash-disk.qss0000644000175000017500000000137614203402514021106 0ustar fengfengQWidget#lineWidget{ background-color: rgba(255,255,255,0.2); width:276px; height:1px; } /* QLabel about */ QLabel#driveNameLabel{ font-size:14px; font-family:Noto Sans CJK SC; font-weight:400; color:rgba(255,255,255,1); line-height:28px; opacity:0.91; } QLabel#capacityLabel{ font-size:14px; font-family:Microsoft YaHei; font-weight:400; color:rgba(255,255,255,0.35); line-height:28px; opacity:0.35; } /* QPushButton about */ QPushButton#Button::pressed{ background:rgba(255,0,0,1); border-radius:4px; width:38px; height:38px; } QPushButton#Button::hover{ background:rgba(255,255,255,0.08); border-radius:4px; width:40px; height:40px; } QPushButton#Button{ background:rgba(255,255,255,0); border-radius:4px; width:40px; height:40px; } ukui-panel-3.0.6.4/ukui-flash-disk/repair-dialog-box.h0000644000175000017500000001301114203402514021021 0ustar fengfeng/* * Copyright (C) 2021 KylinSoft Co., Ltd. * * Authors: * Ding Jing dingjing@kylinos.cn * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include #include #include #include #include #include #include #include #include "device-operation.h" #include "flashdiskdata.h" class QGSettings; class QDBusConnection; class RepairProgressBar; class BaseDialogStyle : public QProxyStyle { Q_OBJECT public: static BaseDialogStyle* getStyle(); public: void polish (QWidget* w) override; void drawControl(QStyle::ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget = nullptr) const override; void drawComplexControl(ComplexControl control, const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget) const override; void drawPrimitive(PrimitiveElement elem, const QStyleOption *option, QPainter *painter, const QWidget *widget) const override; void drawItemText(QPainter *painter, const QRect &rect, int flags, const QPalette &pal, bool enabled, const QString &text, QPalette::ColorRole textRole = QPalette::NoRole) const override; private: BaseDialogStyle (); ~BaseDialogStyle (); private: QPalette mPalette; static BaseDialogStyle* gInstance; }; class BaseDialog : public QDialog { Q_OBJECT public: explicit BaseDialog(QWidget *parent = nullptr); QPalette getPalette(); QPalette getBlackPalette(); QPalette getWhitePalette(); void setTheme(); Q_SIGNALS: void themeChanged (); private: QGSettings* mGSettings = nullptr; }; class RepairDialogBox : public BaseDialog { Q_OBJECT public: explicit RepairDialogBox(GDrive* drive, QWidget *parent = nullptr); explicit RepairDialogBox(GVolume* volume, QWidget *parent = nullptr); QString getDeviceName (); ~RepairDialogBox(); public Q_SLOTS: void onRemountDevice(); private: void initUI(); void isRunning(bool running = false); static void drive_disconnected_callback(GVolumeMonitor* monitor, GDrive* drive, RepairDialogBox* pThis); Q_SIGNALS: void repairOK (RepairDialogBox*); void remountDevice(FDVolumeInfo volumeInfo); private: bool mRepair = false; bool mFormat = false; const int mFixWidth = 480; const int mFixHeight = 240; gulong mVMConnect = 0; QPushButton* mRepairBtn = nullptr; QPushButton* mFormatBtn = nullptr; QString mDeviceName = nullptr; GDrive* mDrive = nullptr; GVolume* mVolume = nullptr; }; class RepairProgressBar : public BaseDialog { Q_OBJECT public: explicit RepairProgressBar(GDrive* drive, QWidget* parent = nullptr); explicit RepairProgressBar(GVolume* volume, QWidget* parent = nullptr); ~RepairProgressBar(); int exec() override; void onStopRepair(bool); void onStartRepair(); private: void initUI (); Q_SIGNALS: void cancel(); void startRepair(); void remountDevice(); private: int mProcess = 0; const int mFixWidth = 480; const int mFixHeight = 240; QTimer* mTimer = nullptr; QProgressBar* mProgress = nullptr; QPushButton* mCancelBtn = nullptr; QThread* mThread = nullptr; DeviceOperation* mDeviceOperation = nullptr; GDrive* mDrive = nullptr; GVolume* mVolume = nullptr; }; class FormateDialog : public BaseDialog { Q_OBJECT public: explicit FormateDialog(GDrive* drive, QWidget *parent = nullptr); explicit FormateDialog(GVolume* drive, QWidget *parent = nullptr); ~FormateDialog(); int exec() override; void onStopFormat(bool); void onStartFormat(); private: void initUI(); Q_SIGNALS: void cancel(); void startFormat(QString type, QString labelName); private: const int mFixWidth = 480; const int mFixHeight = 440; QTimer* mTimer = nullptr; QComboBox* mFSCombox = nullptr; QProgressBar* mProgress = nullptr; QPushButton* mCancelBtn = nullptr; QPushButton* mFormatBtn = nullptr; QCheckBox* mEraseCkbox = nullptr; QLineEdit* mNameEdit = nullptr; QComboBox* mRomSizeCombox = nullptr; QThread* mThread = nullptr; DeviceOperation* mDeviceOperation = nullptr; GDrive* mDrive = nullptr; GVolume* mVolume = nullptr; }; // tip dialog class MessageBox : public BaseDialog { Q_OBJECT public: MessageBox(QString title, QString text, QMessageBox::StandardButtons bt, QWidget* parent = nullptr); Q_SIGNALS: void format(); }; #endif // REPAIRDIALOGBOX_H ukui-panel-3.0.6.4/ukui-flash-disk/test-repair-dialog.cpp0000644000175000017500000000216714203402514021555 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include int main(int argc, char *argv[]) { QApplication app(argc, argv); GDrive* test = nullptr; RepairDialogBox box(test); box.show(); // RepairProgressBar test(QObject::tr("正在进行磁盘修复...")); // test.exec(); // FormateDialog test(nullptr); // test.exec(); return app.exec(); } ukui-panel-3.0.6.4/ukui-flash-disk/MainController.h0000644000175000017500000000254214203402514020453 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include #include #include "mainwindow.h" #include "MacroFile.h" class MainController : public QObject { Q_OBJECT public: static MainController* self(); virtual ~MainController(); int init(); private: explicit MainController(); public: Q_SIGNALS: void notifyWnd(QObject* obj, QEvent *event); private: static MainController *mSelf; MainWindow *m_DiskWindow; }; #endif //_MAINCONTROL_H_ ukui-panel-3.0.6.4/ukui-flash-disk/clickLabel.cpp0000644000175000017500000000227114203402514020102 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see button() == Qt::LeftButton) Q_EMIT clicked(); QLabel::mousePressEvent(event); } //void ClickLabel::paintEvent(QPaintEvent *event){ //// Q_UNUSED(event) //// QStyleOption opt; //// opt.init(this); //// QPainter p(this); //// style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); //} ukui-panel-3.0.6.4/ukui-flash-disk/CMakeLists.txt0000644000175000017500000000556514203402514020122 0ustar fengfengcmake_minimum_required(VERSION 3.1.0) project(ukui-flash-disk) #判断编译器类型,如果是gcc编译器,则在编译选项中加入c++11支持 if(CMAKE_COMPILER_IS_GNUCXX) set(CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}") message(STATUS "optional:-std=c++11") endif(CMAKE_COMPILER_IS_GNUCXX) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) set(CMAKE_AUTOUIC ON) if(CMAKE_VERSION VERSION_LESS "3.7.0") set(CMAKE_INCLUDE_CURRENT_DIR ON) endif() find_package(Qt5 COMPONENTS Widgets Network REQUIRED) find_package(Qt5DBus REQUIRED) find_package(PkgConfig REQUIRED) find_package(KF5WindowSystem REQUIRED) pkg_check_modules(GLIB2 REQUIRED glib-2.0 gio-2.0 udisks2) pkg_check_modules(QGS REQUIRED gsettings-qt) include_directories(${GLIB2_INCLUDE_DIRS}) include_directories(${QGS_INCLUDE_DIRS}) add_executable(ukui-flash-disk ukui-flash-disk.qrc disk-resources/ukui-flash-disk_zh_CN.ts disk-resources/ukui-flash-disk_tr.ts main.cpp mainwindow.cpp qclickwidget.cpp qclickwidget.h UnionVariable.cpp UnionVariable.h ejectInterface.cpp ejectInterface.h clickLabel.h device-operation.h device-operation.cpp clickLabel.cpp device-manager.h device-manager.cpp repair-dialog-box.h repair-dialog-box.cpp MainController.h MainController.cpp MacroFile.h interactivedialog.cpp interactivedialog.h gpartedinterface.cpp gpartedinterface.h mainwindow.ui mainwindow.h fdapplication.cpp fdapplication.h fdframe.cpp fdframe.h flashdiskdata.cpp flashdiskdata.h fdclickwidget.cpp fdclickwidget.h QtSingleApplication/qtsingleapplication.h QtSingleApplication/qtsingleapplication.cpp QtSingleApplication/qtlocalpeer.h QtSingleApplication/qtlocalpeer.cpp datacdrom.h datacdrom.cpp ) add_executable(test-repair-dialog device-manager.h device-manager.cpp repair-dialog-box.h repair-dialog-box.cpp device-operation.h device-operation.cpp test-repair-dialog.cpp ) target_link_libraries(test-repair-dialog Qt5::Widgets Qt5::DBus ${GLIB2_LIBRARIES} ${QGS_LIBRARIES} KF5::WindowSystem) add_definitions(-DQT_NO_KEYWORDS) add_definitions(-DQT_MESSAGELOGCONTEXT) target_link_libraries(${PROJECT_NAME} Qt5::Widgets Qt5::DBus Qt5::Network ${GLIB2_LIBRARIES} ${QGS_LIBRARIES} KF5::WindowSystem -lukui-log4qt) install(TARGETS ukui-flash-disk DESTINATION bin) install(FILES disk-resources/ukui-flash-disk.desktop DESTINATION "/etc/xdg/autostart/" COMPONENT Runtime ) install(FILES ukui-flash-disk.qrc disk-resources/ukui-flash-disk_zh_CN.qm disk-resources/ukui-flash-disk_tr.qm DESTINATION "/usr/share/ukui/ukui-panel/" COMPONENT Runtime ) install(FILES disk-resources/org.ukui.flash-disk.autoload.gschema.xml DESTINATION "/usr/share/glib-2.0/schemas" COMPONENT Runtime ) ukui-panel-3.0.6.4/ukui-flash-disk/QtSingleApplication/0000755000175000017500000000000014203402514021261 5ustar fengfengukui-panel-3.0.6.4/ukui-flash-disk/QtSingleApplication/qtsinglecoreapplication.h0000644000175000017500000000502514203402514026357 0ustar fengfeng/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Solutions component. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QTSINGLECOREAPPLICATION_H #define QTSINGLECOREAPPLICATION_H #include class QtLocalPeer; class QtSingleCoreApplication : public QCoreApplication { Q_OBJECT public: QtSingleCoreApplication(int &argc, char **argv); QtSingleCoreApplication(const QString &id, int &argc, char **argv); bool isRunning(); QString id() const; public Q_SLOTS: bool sendMessage(const QString &message, int timeout = 5000); Q_SIGNALS: void messageReceived(const QString &message); private: QtLocalPeer* peer; }; #endif // QTSINGLECOREAPPLICATION_H ukui-panel-3.0.6.4/ukui-flash-disk/QtSingleApplication/qtlockedfile.cpp0000644000175000017500000001374214203402514024442 0ustar fengfeng/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Solutions component. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qtlockedfile.h" /*! \class QtLockedFile \brief The QtLockedFile class extends QFile with advisory locking functions. A file may be locked in read or write mode. Multiple instances of \e QtLockedFile, created in multiple processes running on the same machine, may have a file locked in read mode. Exactly one instance may have it locked in write mode. A read and a write lock cannot exist simultaneously on the same file. The file locks are advisory. This means that nothing prevents another process from manipulating a locked file using QFile or file system functions offered by the OS. Serialization is only guaranteed if all processes that access the file use QLockedFile. Also, while holding a lock on a file, a process must not open the same file again (through any API), or locks can be unexpectedly lost. The lock provided by an instance of \e QtLockedFile is released whenever the program terminates. This is true even when the program crashes and no destructors are called. */ /*! \enum QtLockedFile::LockMode This enum describes the available lock modes. \value ReadLock A read lock. \value WriteLock A write lock. \value NoLock Neither a read lock nor a write lock. */ /*! Constructs an unlocked \e QtLockedFile object. This constructor behaves in the same way as \e QFile::QFile(). \sa QFile::QFile() */ QtLockedFile::QtLockedFile() : QFile() { #ifdef Q_OS_WIN wmutex = 0; rmutex = 0; #endif m_lock_mode = NoLock; } /*! Constructs an unlocked QtLockedFile object with file \a name. This constructor behaves in the same way as \e QFile::QFile(const QString&). \sa QFile::QFile() */ QtLockedFile::QtLockedFile(const QString &name) : QFile(name) { #ifdef Q_OS_WIN wmutex = 0; rmutex = 0; #endif m_lock_mode = NoLock; } /*! Opens the file in OpenMode \a mode. This is identical to QFile::open(), with the one exception that the Truncate mode flag is disallowed. Truncation would conflict with the advisory file locking, since the file would be modified before the write lock is obtained. If truncation is required, use resize(0) after obtaining the write lock. Returns true if successful; otherwise false. \sa QFile::open(), QFile::resize() */ bool QtLockedFile::open(OpenMode mode) { if (mode & QIODevice::Truncate) { qWarning("QtLockedFile::open(): Truncate mode not allowed."); return false; } return QFile::open(mode); } /*! Returns \e true if this object has a in read or write lock; otherwise returns \e false. \sa lockMode() */ bool QtLockedFile::isLocked() const { return m_lock_mode != NoLock; } /*! Returns the type of lock currently held by this object, or \e QtLockedFile::NoLock. \sa isLocked() */ QtLockedFile::LockMode QtLockedFile::lockMode() const { return m_lock_mode; } /*! \fn bool QtLockedFile::lock(LockMode mode, bool block = true) Obtains a lock of type \a mode. The file must be opened before it can be locked. If \a block is true, this function will block until the lock is aquired. If \a block is false, this function returns \e false immediately if the lock cannot be aquired. If this object already has a lock of type \a mode, this function returns \e true immediately. If this object has a lock of a different type than \a mode, the lock is first released and then a new lock is obtained. This function returns \e true if, after it executes, the file is locked by this object, and \e false otherwise. \sa unlock(), isLocked(), lockMode() */ /*! \fn bool QtLockedFile::unlock() Releases a lock. If the object has no lock, this function returns immediately. This function returns \e true if, after it executes, the file is not locked by this object, and \e false otherwise. \sa lock(), isLocked(), lockMode() */ /*! \fn QtLockedFile::~QtLockedFile() Destroys the \e QtLockedFile object. If any locks were held, they are released. */ ukui-panel-3.0.6.4/ukui-flash-disk/QtSingleApplication/qtlocalpeer.cpp0000644000175000017500000001543614203402514024311 0ustar fengfeng/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Solutions component. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qtlocalpeer.h" #include #include #include #if defined(Q_OS_WIN) #include #include typedef BOOL(WINAPI*PProcessIdToSessionId)(DWORD,DWORD*); static PProcessIdToSessionId pProcessIdToSessionId = 0; #endif #if defined(Q_OS_UNIX) #include #include #include #endif namespace QtLP_Private { #include "qtlockedfile.cpp" #if defined(Q_OS_WIN) #include "qtlockedfile_win.cpp" #else #include "qtlockedfile_unix.cpp" #endif } const char* QtLocalPeer::ack = "ack"; QtLocalPeer::QtLocalPeer(QObject* parent, const QString &appId) : QObject(parent), id(appId) { QString prefix = id; if (id.isEmpty()) { id = QCoreApplication::applicationFilePath(); #if defined(Q_OS_WIN) id = id.toLower(); #endif prefix = id.section(QLatin1Char('/'), -1); } prefix.remove(QRegExp("[^a-zA-Z]")); prefix.truncate(6); QByteArray idc = id.toUtf8(); quint16 idNum = qChecksum(idc.constData(), idc.size()); socketName = QLatin1String("qtsingleapp-") + prefix + QLatin1Char('-') + QString::number(idNum, 16); #if defined(Q_OS_WIN) if (!pProcessIdToSessionId) { QLibrary lib("kernel32"); pProcessIdToSessionId = (PProcessIdToSessionId)lib.resolve("ProcessIdToSessionId"); } if (pProcessIdToSessionId) { DWORD sessionId = 0; pProcessIdToSessionId(GetCurrentProcessId(), &sessionId); socketName += QLatin1Char('-') + QString::number(sessionId, 16); } #else socketName += QLatin1Char('-') + QString::number(::getuid(), 16); #endif server = new QLocalServer(this); QString lockName = QDir(QDir::tempPath()).absolutePath() + QLatin1Char('/') + socketName + QLatin1String("-lockfile"); lockFile.setFileName(lockName); lockFile.open(QIODevice::ReadWrite); } bool QtLocalPeer::isClient() { if (lockFile.isLocked()) return false; if (!lockFile.lock(QtLP_Private::QtLockedFile::WriteLock, false)) return true; bool res = server->listen(socketName); #if defined(Q_OS_UNIX) && (QT_VERSION >= QT_VERSION_CHECK(4,5,0)) // ### Workaround if (!res && server->serverError() == QAbstractSocket::AddressInUseError) { QFile::remove(QDir::cleanPath(QDir::tempPath())+QLatin1Char('/')+socketName); res = server->listen(socketName); } #endif if (!res) qWarning("QtSingleCoreApplication: listen on local socket failed, %s", qPrintable(server->errorString())); QObject::connect(server, SIGNAL(newConnection()), SLOT(receiveConnection())); return false; } bool QtLocalPeer::sendMessage(const QString &message, int timeout) { if (!isClient()) return false; QLocalSocket socket; bool connOk = false; for(int i = 0; i < 2; i++) { // Try twice, in case the other instance is just starting up socket.connectToServer(socketName); connOk = socket.waitForConnected(timeout/2); if (connOk || i) break; int ms = 250; #if defined(Q_OS_WIN) Sleep(DWORD(ms)); #else struct timespec ts = { ms / 1000, (ms % 1000) * 1000 * 1000 }; nanosleep(&ts, NULL); #endif } if (!connOk) return false; QByteArray uMsg(message.toUtf8()); QDataStream ds(&socket); ds.writeBytes(uMsg.constData(), uMsg.size()); bool res = socket.waitForBytesWritten(timeout); if (res) { res &= socket.waitForReadyRead(timeout); // wait for ack if (res) res &= (socket.read(qstrlen(ack)) == ack); } return res; } void QtLocalPeer::receiveConnection() { QLocalSocket* socket = server->nextPendingConnection(); if (!socket) return; while (true) { if (socket->state() == QLocalSocket::UnconnectedState) { qWarning("QtLocalPeer: Peer disconnected"); delete socket; return; } if (socket->bytesAvailable() >= qint64(sizeof(quint32))) break; socket->waitForReadyRead(); } QDataStream ds(socket); QByteArray uMsg; quint32 remaining; ds >> remaining; uMsg.resize(remaining); int got = 0; char* uMsgBuf = uMsg.data(); do { got = ds.readRawData(uMsgBuf, remaining); remaining -= got; uMsgBuf += got; } while (remaining && got >= 0 && socket->waitForReadyRead(2000)); if (got < 0) { qWarning("QtLocalPeer: Message reception failed %s", socket->errorString().toLatin1().constData()); delete socket; return; } QString message(QString::fromUtf8(uMsg)); socket->write(ack, qstrlen(ack)); socket->waitForBytesWritten(1000); socket->waitForDisconnected(1000); // make sure client reads ack delete socket; Q_EMIT messageReceived(message); //### (might take a long time to return) } ukui-panel-3.0.6.4/ukui-flash-disk/QtSingleApplication/qtlocalpeer.h0000644000175000017500000000520514203402514023747 0ustar fengfeng/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Solutions component. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QTLOCALPEER_H #define QTLOCALPEER_H #include #include #include #include "qtlockedfile.h" class QtLocalPeer : public QObject { Q_OBJECT public: QtLocalPeer(QObject *parent = 0, const QString &appId = QString()); bool isClient(); bool sendMessage(const QString &message, int timeout); QString applicationId() const { return id; } Q_SIGNALS: void messageReceived(const QString &message); protected Q_SLOTS: void receiveConnection(); protected: QString id; QString socketName; QLocalServer* server; QtLP_Private::QtLockedFile lockFile; private: static const char* ack; }; #endif // QTLOCALPEER_H ukui-panel-3.0.6.4/ukui-flash-disk/QtSingleApplication/qtlockedfile_win.cpp0000644000175000017500000001466114203402514025320 0ustar fengfeng/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Solutions component. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qtlockedfile.h" #include #include #define MUTEX_PREFIX "QtLockedFile mutex " // Maximum number of concurrent read locks. Must not be greater than MAXIMUM_WAIT_OBJECTS #define MAX_READERS MAXIMUM_WAIT_OBJECTS #if QT_VERSION >= 0x050000 #define QT_WA(unicode, ansi) unicode #endif Qt::HANDLE QtLockedFile::getMutexHandle(int idx, bool doCreate) { if (mutexname.isEmpty()) { QFileInfo fi(*this); mutexname = QString::fromLatin1(MUTEX_PREFIX) + fi.absoluteFilePath().toLower(); } QString mname(mutexname); if (idx >= 0) mname += QString::number(idx); Qt::HANDLE mutex; if (doCreate) { QT_WA( { mutex = CreateMutexW(NULL, FALSE, (TCHAR*)mname.utf16()); }, { mutex = CreateMutexA(NULL, FALSE, mname.toLocal8Bit().constData()); } ); if (!mutex) { qErrnoWarning("QtLockedFile::lock(): CreateMutex failed"); return 0; } } else { QT_WA( { mutex = OpenMutexW(SYNCHRONIZE | MUTEX_MODIFY_STATE, FALSE, (TCHAR*)mname.utf16()); }, { mutex = OpenMutexA(SYNCHRONIZE | MUTEX_MODIFY_STATE, FALSE, mname.toLocal8Bit().constData()); } ); if (!mutex) { if (GetLastError() != ERROR_FILE_NOT_FOUND) qErrnoWarning("QtLockedFile::lock(): OpenMutex failed"); return 0; } } return mutex; } bool QtLockedFile::waitMutex(Qt::HANDLE mutex, bool doBlock) { Q_ASSERT(mutex); DWORD res = WaitForSingleObject(mutex, doBlock ? INFINITE : 0); switch (res) { case WAIT_OBJECT_0: case WAIT_ABANDONED: return true; break; case WAIT_TIMEOUT: break; default: qErrnoWarning("QtLockedFile::lock(): WaitForSingleObject failed"); } return false; } bool QtLockedFile::lock(LockMode mode, bool block) { if (!isOpen()) { qWarning("QtLockedFile::lock(): file is not opened"); return false; } if (mode == NoLock) return unlock(); if (mode == m_lock_mode) return true; if (m_lock_mode != NoLock) unlock(); if (!wmutex && !(wmutex = getMutexHandle(-1, true))) return false; if (!waitMutex(wmutex, block)) return false; if (mode == ReadLock) { int idx = 0; for (; idx < MAX_READERS; idx++) { rmutex = getMutexHandle(idx, false); if (!rmutex || waitMutex(rmutex, false)) break; CloseHandle(rmutex); } bool ok = true; if (idx >= MAX_READERS) { qWarning("QtLockedFile::lock(): too many readers"); rmutex = 0; ok = false; } else if (!rmutex) { rmutex = getMutexHandle(idx, true); if (!rmutex || !waitMutex(rmutex, false)) ok = false; } if (!ok && rmutex) { CloseHandle(rmutex); rmutex = 0; } ReleaseMutex(wmutex); if (!ok) return false; } else { Q_ASSERT(rmutexes.isEmpty()); for (int i = 0; i < MAX_READERS; i++) { Qt::HANDLE mutex = getMutexHandle(i, false); if (mutex) rmutexes.append(mutex); } if (rmutexes.size()) { DWORD res = WaitForMultipleObjects(rmutexes.size(), rmutexes.constData(), TRUE, block ? INFINITE : 0); if (res != WAIT_OBJECT_0 && res != WAIT_ABANDONED) { if (res != WAIT_TIMEOUT) qErrnoWarning("QtLockedFile::lock(): WaitForMultipleObjects failed"); m_lock_mode = WriteLock; // trick unlock() to clean up - semiyucky unlock(); return false; } } } m_lock_mode = mode; return true; } bool QtLockedFile::unlock() { if (!isOpen()) { qWarning("QtLockedFile::unlock(): file is not opened"); return false; } if (!isLocked()) return true; if (m_lock_mode == ReadLock) { ReleaseMutex(rmutex); CloseHandle(rmutex); rmutex = 0; } else { foreach(Qt::HANDLE mutex, rmutexes) { ReleaseMutex(mutex); CloseHandle(mutex); } rmutexes.clear(); ReleaseMutex(wmutex); } m_lock_mode = QtLockedFile::NoLock; return true; } QtLockedFile::~QtLockedFile() { if (isOpen()) unlock(); if (wmutex) CloseHandle(wmutex); } ukui-panel-3.0.6.4/ukui-flash-disk/QtSingleApplication/qtlockedfile_unix.cpp0000644000175000017500000000661414203402514025505 0ustar fengfeng/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Solutions component. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include #include #include "qtlockedfile.h" bool QtLockedFile::lock(LockMode mode, bool block) { if (!isOpen()) { qWarning("QtLockedFile::lock(): file is not opened"); return false; } if (mode == NoLock) return unlock(); if (mode == m_lock_mode) return true; if (m_lock_mode != NoLock) unlock(); struct flock fl; fl.l_whence = SEEK_SET; fl.l_start = 0; fl.l_len = 0; fl.l_type = (mode == ReadLock) ? F_RDLCK : F_WRLCK; int cmd = block ? F_SETLKW : F_SETLK; int ret = fcntl(handle(), cmd, &fl); if (ret == -1) { if (errno != EINTR && errno != EAGAIN) qWarning("QtLockedFile::lock(): fcntl: %s", strerror(errno)); return false; } m_lock_mode = mode; return true; } bool QtLockedFile::unlock() { if (!isOpen()) { qWarning("QtLockedFile::unlock(): file is not opened"); return false; } if (!isLocked()) return true; struct flock fl; fl.l_whence = SEEK_SET; fl.l_start = 0; fl.l_len = 0; fl.l_type = F_UNLCK; int ret = fcntl(handle(), F_SETLKW, &fl); if (ret == -1) { qWarning("QtLockedFile::lock(): fcntl: %s", strerror(errno)); return false; } m_lock_mode = NoLock; return true; } QtLockedFile::~QtLockedFile() { if (isOpen()) unlock(); } ukui-panel-3.0.6.4/ukui-flash-disk/QtSingleApplication/qtsinglecoreapplication.pri0000644000175000017500000000056214203402514026723 0ustar fengfengQT += network INCLUDEPATH += $$PWD DEPENDPATH += $$PWD HEADERS += $$PWD/qtsinglecoreapplication.h \ $$PWD/qtlocalpeer.h SOURCES += $$PWD/qtsinglecoreapplication.cpp \ $$PWD/qtlocalpeer.cpp win32:contains(TEMPLATE, lib):contains(CONFIG, shared) { DEFINES += QT_QTSINGLECOREAPPLICATION_EXPORT=__declspec(dllexport) } ukui-panel-3.0.6.4/ukui-flash-disk/QtSingleApplication/qtsingleapplication.pri0000644000175000017500000000106114203402514026045 0ustar fengfengINCLUDEPATH += $$PWD DEPENDPATH += $$PWD QT *= network greaterThan(QT_MAJOR_VERSION, 4): QT *= widgets qtsingleapplication-uselib:!qtsingleapplication-buildlib { LIBS += -L$$QTSINGLEAPPLICATION_LIBDIR -l$$QTSINGLEAPPLICATION_LIBNAME } else { SOURCES += $$PWD/qtsingleapplication.cpp $$PWD/qtlocalpeer.cpp HEADERS += $$PWD/qtsingleapplication.h $$PWD/qtlocalpeer.h } win32 { contains(TEMPLATE, lib):contains(CONFIG, shared):DEFINES += QT_QTSINGLEAPPLICATION_EXPORT else:qtsingleapplication-uselib:DEFINES += QT_QTSINGLEAPPLICATION_IMPORT } ukui-panel-3.0.6.4/ukui-flash-disk/QtSingleApplication/qtsingleapplication.h0000644000175000017500000000761714203402514025517 0ustar fengfeng/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Solutions component. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QTSINGLEAPPLICATION_H #define QTSINGLEAPPLICATION_H #include class QtLocalPeer; #if defined(Q_OS_WIN) # if !defined(QT_QTSINGLEAPPLICATION_EXPORT) && !defined(QT_QTSINGLEAPPLICATION_IMPORT) # define QT_QTSINGLEAPPLICATION_EXPORT # elif defined(QT_QTSINGLEAPPLICATION_IMPORT) # if defined(QT_QTSINGLEAPPLICATION_EXPORT) # undef QT_QTSINGLEAPPLICATION_EXPORT # endif # define QT_QTSINGLEAPPLICATION_EXPORT __declspec(dllimport) # elif defined(QT_QTSINGLEAPPLICATION_EXPORT) # undef QT_QTSINGLEAPPLICATION_EXPORT # define QT_QTSINGLEAPPLICATION_EXPORT __declspec(dllexport) # endif #else # define QT_QTSINGLEAPPLICATION_EXPORT #endif class QT_QTSINGLEAPPLICATION_EXPORT QtSingleApplication : public QApplication { Q_OBJECT public: QtSingleApplication(int &argc, char **argv, bool GUIenabled = true); QtSingleApplication(const QString &id, int &argc, char **argv); #if QT_VERSION < 0x050000 QtSingleApplication(int &argc, char **argv, Type type); # if defined(Q_WS_X11) QtSingleApplication(Display* dpy, Qt::HANDLE visual = 0, Qt::HANDLE colormap = 0); QtSingleApplication(Display *dpy, int &argc, char **argv, Qt::HANDLE visual = 0, Qt::HANDLE cmap= 0); QtSingleApplication(Display* dpy, const QString &appId, int argc, char **argv, Qt::HANDLE visual = 0, Qt::HANDLE colormap = 0); # endif // Q_WS_X11 #endif // QT_VERSION < 0x050000 bool isRunning(); QString id() const; void setActivationWindow(QWidget* aw, bool activateOnMessage = true); QWidget* activationWindow() const; // Obsolete: void initialize(bool dummy = true) { isRunning(); Q_UNUSED(dummy) } public Q_SLOTS: bool sendMessage(const QString &message, int timeout = 5000); void activateWindow(); Q_SIGNALS: void messageReceived(const QString &message); private: void sysInit(const QString &appId = QString()); QtLocalPeer *peer; QWidget *actWin; }; #endif // QTSINGLEAPPLICATION_H ukui-panel-3.0.6.4/ukui-flash-disk/QtSingleApplication/qtlockedfile.h0000644000175000017500000000630714203402514024106 0ustar fengfeng/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Solutions component. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QTLOCKEDFILE_H #define QTLOCKEDFILE_H #include #ifdef Q_OS_WIN #include #endif #if defined(Q_OS_WIN) # if !defined(QT_QTLOCKEDFILE_EXPORT) && !defined(QT_QTLOCKEDFILE_IMPORT) # define QT_QTLOCKEDFILE_EXPORT # elif defined(QT_QTLOCKEDFILE_IMPORT) # if defined(QT_QTLOCKEDFILE_EXPORT) # undef QT_QTLOCKEDFILE_EXPORT # endif # define QT_QTLOCKEDFILE_EXPORT __declspec(dllimport) # elif defined(QT_QTLOCKEDFILE_EXPORT) # undef QT_QTLOCKEDFILE_EXPORT # define QT_QTLOCKEDFILE_EXPORT __declspec(dllexport) # endif #else # define QT_QTLOCKEDFILE_EXPORT #endif namespace QtLP_Private { class QT_QTLOCKEDFILE_EXPORT QtLockedFile : public QFile { public: enum LockMode { NoLock = 0, ReadLock, WriteLock }; QtLockedFile(); QtLockedFile(const QString &name); ~QtLockedFile(); bool open(OpenMode mode); bool lock(LockMode mode, bool block = true); bool unlock(); bool isLocked() const; LockMode lockMode() const; private: #ifdef Q_OS_WIN Qt::HANDLE wmutex; Qt::HANDLE rmutex; QVector rmutexes; QString mutexname; Qt::HANDLE getMutexHandle(int idx, bool doCreate); bool waitMutex(Qt::HANDLE mutex, bool doBlock); #endif LockMode m_lock_mode; }; } #endif ukui-panel-3.0.6.4/ukui-flash-disk/QtSingleApplication/QtSingleApplication0000644000175000017500000000004114203402514025111 0ustar fengfeng#include "qtsingleapplication.h" ukui-panel-3.0.6.4/ukui-flash-disk/QtSingleApplication/qtsingleapplication.cpp0000644000175000017500000002704614203402514026050 0ustar fengfeng/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Solutions component. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qtsingleapplication.h" #include "qtlocalpeer.h" #include /*! \class QtSingleApplication qtsingleapplication.h \brief The QtSingleApplication class provides an API to detect and communicate with running instances of an application. This class allows you to create applications where only one instance should be running at a time. I.e., if the user tries to launch another instance, the already running instance will be activated instead. Another usecase is a client-server system, where the first started instance will assume the role of server, and the later instances will act as clients of that server. By default, the full path of the executable file is used to determine whether two processes are instances of the same application. You can also provide an explicit identifier string that will be compared instead. The application should create the QtSingleApplication object early in the startup phase, and call isRunning() to find out if another instance of this application is already running. If isRunning() returns false, it means that no other instance is running, and this instance has assumed the role as the running instance. In this case, the application should continue with the initialization of the application user interface before entering the event loop with exec(), as normal. The messageReceived() signal will be emitted when the running application receives messages from another instance of the same application. When a message is received it might be helpful to the user to raise the application so that it becomes visible. To facilitate this, QtSingleApplication provides the setActivationWindow() function and the activateWindow() slot. If isRunning() returns true, another instance is already running. It may be alerted to the fact that another instance has started by using the sendMessage() function. Also data such as startup parameters (e.g. the name of the file the user wanted this new instance to open) can be passed to the running instance with this function. Then, the application should terminate (or enter client mode). If isRunning() returns true, but sendMessage() fails, that is an indication that the running instance is frozen. Here's an example that shows how to convert an existing application to use QtSingleApplication. It is very simple and does not make use of all QtSingleApplication's functionality (see the examples for that). \code // Original int main(int argc, char **argv) { QApplication app(argc, argv); MyMainWidget mmw; mmw.show(); return app.exec(); } // Single instance int main(int argc, char **argv) { QtSingleApplication app(argc, argv); if (app.isRunning()) return !app.sendMessage(someDataString); MyMainWidget mmw; app.setActivationWindow(&mmw); mmw.show(); return app.exec(); } \endcode Once this QtSingleApplication instance is destroyed (normally when the process exits or crashes), when the user next attempts to run the application this instance will not, of course, be encountered. The next instance to call isRunning() or sendMessage() will assume the role as the new running instance. For console (non-GUI) applications, QtSingleCoreApplication may be used instead of this class, to avoid the dependency on the QtGui library. \sa QtSingleCoreApplication */ void QtSingleApplication::sysInit(const QString &appId) { actWin = 0; peer = new QtLocalPeer(this, appId); connect(peer, SIGNAL(messageReceived(const QString&)), SIGNAL(messageReceived(const QString&))); } /*! Creates a QtSingleApplication object. The application identifier will be QCoreApplication::applicationFilePath(). \a argc, \a argv, and \a GUIenabled are passed on to the QAppliation constructor. If you are creating a console application (i.e. setting \a GUIenabled to false), you may consider using QtSingleCoreApplication instead. */ QtSingleApplication::QtSingleApplication(int &argc, char **argv, bool GUIenabled) : QApplication(argc, argv, GUIenabled) { sysInit(); } /*! Creates a QtSingleApplication object with the application identifier \a appId. \a argc and \a argv are passed on to the QAppliation constructor. */ QtSingleApplication::QtSingleApplication(const QString &appId, int &argc, char **argv) : QApplication(argc, argv) { sysInit(appId); } #if QT_VERSION < 0x050000 /*! Creates a QtSingleApplication object. The application identifier will be QCoreApplication::applicationFilePath(). \a argc, \a argv, and \a type are passed on to the QAppliation constructor. */ QtSingleApplication::QtSingleApplication(int &argc, char **argv, Type type) : QApplication(argc, argv, type) { sysInit(); } # if defined(Q_WS_X11) /*! Special constructor for X11, ref. the documentation of QApplication's corresponding constructor. The application identifier will be QCoreApplication::applicationFilePath(). \a dpy, \a visual, and \a cmap are passed on to the QApplication constructor. */ QtSingleApplication::QtSingleApplication(Display* dpy, Qt::HANDLE visual, Qt::HANDLE cmap) : QApplication(dpy, visual, cmap) { sysInit(); } /*! Special constructor for X11, ref. the documentation of QApplication's corresponding constructor. The application identifier will be QCoreApplication::applicationFilePath(). \a dpy, \a argc, \a argv, \a visual, and \a cmap are passed on to the QApplication constructor. */ QtSingleApplication::QtSingleApplication(Display *dpy, int &argc, char **argv, Qt::HANDLE visual, Qt::HANDLE cmap) : QApplication(dpy, argc, argv, visual, cmap) { sysInit(); } /*! Special constructor for X11, ref. the documentation of QApplication's corresponding constructor. The application identifier will be \a appId. \a dpy, \a argc, \a argv, \a visual, and \a cmap are passed on to the QApplication constructor. */ QtSingleApplication::QtSingleApplication(Display* dpy, const QString &appId, int argc, char **argv, Qt::HANDLE visual, Qt::HANDLE cmap) : QApplication(dpy, argc, argv, visual, cmap) { sysInit(appId); } # endif // Q_WS_X11 #endif // QT_VERSION < 0x050000 /*! Returns true if another instance of this application is running; otherwise false. This function does not find instances of this application that are being run by a different user (on Windows: that are running in another session). \sa sendMessage() */ bool QtSingleApplication::isRunning() { return peer->isClient(); } /*! Tries to send the text \a message to the currently running instance. The QtSingleApplication object in the running instance will emit the messageReceived() signal when it receives the message. This function returns true if the message has been sent to, and processed by, the current instance. If there is no instance currently running, or if the running instance fails to process the message within \a timeout milliseconds, this function return false. \sa isRunning(), messageReceived() */ bool QtSingleApplication::sendMessage(const QString &message, int timeout) { return peer->sendMessage(message, timeout); } /*! Returns the application identifier. Two processes with the same identifier will be regarded as instances of the same application. */ QString QtSingleApplication::id() const { return peer->applicationId(); } /*! Sets the activation window of this application to \a aw. The activation window is the widget that will be activated by activateWindow(). This is typically the application's main window. If \a activateOnMessage is true (the default), the window will be activated automatically every time a message is received, just prior to the messageReceived() signal being emitted. \sa activateWindow(), messageReceived() */ void QtSingleApplication::setActivationWindow(QWidget* aw, bool activateOnMessage) { actWin = aw; if (activateOnMessage) connect(peer, SIGNAL(messageReceived(const QString&)), this, SLOT(activateWindow())); else disconnect(peer, SIGNAL(messageReceived(const QString&)), this, SLOT(activateWindow())); } /*! Returns the applications activation window if one has been set by calling setActivationWindow(), otherwise returns 0. \sa setActivationWindow() */ QWidget* QtSingleApplication::activationWindow() const { return actWin; } /*! De-minimizes, raises, and activates this application's activation window. This function does nothing if no activation window has been set. This is a convenience function to show the user that this application instance has been activated when he has tried to start another instance. This function should typically be called in response to the messageReceived() signal. By default, that will happen automatically, if an activation window has been set. \sa setActivationWindow(), messageReceived(), initialize() */ void QtSingleApplication::activateWindow() { if (actWin) { actWin->setWindowState(actWin->windowState() & ~Qt::WindowMinimized); actWin->raise(); actWin->showNormal(); actWin->activateWindow(); } } /*! \fn void QtSingleApplication::messageReceived(const QString& message) This signal is emitted when the current instance receives a \a message from another instance of this application. \sa sendMessage(), setActivationWindow(), activateWindow() */ /*! \fn void QtSingleApplication::initialize(bool dummy = true) \obsolete */ ukui-panel-3.0.6.4/ukui-flash-disk/QtSingleApplication/qtsinglecoreapplication.cpp0000644000175000017500000001235514203402514026716 0ustar fengfeng/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Solutions component. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qtsinglecoreapplication.h" #include "qtlocalpeer.h" /*! \class QtSingleCoreApplication qtsinglecoreapplication.h \brief A variant of the QtSingleApplication class for non-GUI applications. This class is a variant of QtSingleApplication suited for use in console (non-GUI) applications. It is an extension of QCoreApplication (instead of QApplication). It does not require the QtGui library. The API and usage is identical to QtSingleApplication, except that functions relating to the "activation window" are not present, for obvious reasons. Please refer to the QtSingleApplication documentation for explanation of the usage. A QtSingleCoreApplication instance can communicate to a QtSingleApplication instance if they share the same application id. Hence, this class can be used to create a light-weight command-line tool that sends commands to a GUI application. \sa QtSingleApplication */ /*! Creates a QtSingleCoreApplication object. The application identifier will be QCoreApplication::applicationFilePath(). \a argc and \a argv are passed on to the QCoreAppliation constructor. */ QtSingleCoreApplication::QtSingleCoreApplication(int &argc, char **argv) : QCoreApplication(argc, argv) { peer = new QtLocalPeer(this); connect(peer, SIGNAL(messageReceived(const QString&)), SIGNAL(messageReceived(const QString&))); } /*! Creates a QtSingleCoreApplication object with the application identifier \a appId. \a argc and \a argv are passed on to the QCoreAppliation constructor. */ QtSingleCoreApplication::QtSingleCoreApplication(const QString &appId, int &argc, char **argv) : QCoreApplication(argc, argv) { peer = new QtLocalPeer(this, appId); connect(peer, SIGNAL(messageReceived(const QString&)), SIGNAL(messageReceived(const QString&))); } /*! Returns true if another instance of this application is running; otherwise false. This function does not find instances of this application that are being run by a different user (on Windows: that are running in another session). \sa sendMessage() */ bool QtSingleCoreApplication::isRunning() { return peer->isClient(); } /*! Tries to send the text \a message to the currently running instance. The QtSingleCoreApplication object in the running instance will emit the messageReceived() signal when it receives the message. This function returns true if the message has been sent to, and processed by, the current instance. If there is no instance currently running, or if the running instance fails to process the message within \a timeout milliseconds, this function return false. \sa isRunning(), messageReceived() */ bool QtSingleCoreApplication::sendMessage(const QString &message, int timeout) { return peer->sendMessage(message, timeout); } /*! Returns the application identifier. Two processes with the same identifier will be regarded as instances of the same application. */ QString QtSingleCoreApplication::id() const { return peer->applicationId(); } /*! \fn void QtSingleCoreApplication::messageReceived(const QString& message) This signal is emitted when the current instance receives a \a message from another instance of this application. \sa sendMessage() */ ukui-panel-3.0.6.4/ukui-flash-disk/QtSingleApplication/QtLockedFile0000644000175000017500000000003214203402514023505 0ustar fengfeng#include "qtlockedfile.h" ukui-panel-3.0.6.4/ukui-flash-disk/fdframe.cpp0000644000175000017500000000536714203402514017472 0ustar fengfeng/* * Copyright (C) 2021 KylinSoft Co., Ltd. * * Authors: * Yang Min yangmin@kylinos.cn * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include #include #include #include "fdframe.h" #define THEME_UKFD_TRANS "org.ukui.control-center.personalise" FDFrame::FDFrame(QWidget* parent) : QFrame(parent) { setWindowFlags(Qt::FramelessWindowHint | Qt::ToolTip); setAttribute(Qt::WA_AlwaysShowToolTips); setAttribute(Qt::WA_TranslucentBackground); //setWindowOpacity(0.8); initOpacityGSettings(); KWindowEffects::enableBlurBehind(winId(), true); } FDFrame::~FDFrame() { if (m_gsTransOpacity) { delete m_gsTransOpacity; m_gsTransOpacity = nullptr; } } void FDFrame::initOpacityGSettings() { const QByteArray idtrans(THEME_UKFD_TRANS); if(QGSettings::isSchemaInstalled(idtrans)) { m_gsTransOpacity = new QGSettings(idtrans); } if (!m_gsTransOpacity) { m_curTransOpacity = 1; return; } connect(m_gsTransOpacity, &QGSettings::changed, this, [=](const QString &key) { if (key == "transparency") { QStringList keys = m_gsTransOpacity->keys(); if (keys.contains("transparency")) { m_curTransOpacity = m_gsTransOpacity->get("transparency").toString().toDouble(); repaint(); } } }); QStringList keys = m_gsTransOpacity->keys(); if(keys.contains("transparency")) { m_curTransOpacity = m_gsTransOpacity->get("transparency").toString().toDouble(); } } void FDFrame::paintEvent(QPaintEvent * event) { QPainterPath path; QPainter painter(this); painter.setOpacity(m_curTransOpacity); painter.setRenderHint(QPainter::Antialiasing); // 反锯齿; painter.setClipping(true); painter.setPen(Qt::transparent); path.addRoundedRect(this->rect(), 12, 12); path.setFillRule(Qt::WindingFill); painter.setBrush(this->palette().color(QPalette::Base)); painter.setPen(Qt::transparent); painter.drawPath(path); QFrame::paintEvent(event); } ukui-panel-3.0.6.4/ukui-flash-disk/UnionVariable.cpp0000644000175000017500000001212514203402514020612 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include static QList gmountList; QList *findGMountList() { return &gmountList; } static QList gtelevolumeList; QList *findTeleGVolumeList() { return >elevolumeList; } static QList gvolumeList; QList *findGVolumeList() { return &gvolumeList; } static QList gdriveList; QList *findGDriveList() { return &gdriveList; } static QList gtelemountList; QList *findTeleGMountList() { return >elemountList; } QString getElidedText(QFont font, QString str, int MaxWidth) { if (str.isEmpty()) { return ""; } QFontMetrics fontWidth(font); //计算字符串宽度 //calculat the width of the string int width = fontWidth.width(str); //当字符串宽度大于最大宽度时进行转换 //Convert when string width is greater than maximum width if (width >= MaxWidth) { //右部显示省略号 //show by ellipsis in right str = fontWidth.elidedText(str, Qt::ElideRight, MaxWidth); } //返回处理后的字符串 //return the string that is been handled return str; } void handleVolumeLabelForFat32Me(QString &volumeName,const QString &unixDeviceName){ QFileInfoList diskList; QFileInfo diskLabel; QDir diskDir; QString partitionName,linkTarget; QString tmpName,finalName; int i; diskDir.setPath("/dev/disk/by-label"); if(!diskDir.exists()) //this means: volume has no name. return; // or there no mobile devices. diskList = diskDir.entryInfoList(); //all file from dir. /* eg: unixDeviceName == "/dev/sdb4" * partitionName == "sdb4" */ partitionName = unixDeviceName.mid(unixDeviceName.lastIndexOf('/')+1); for(i = 0; i < diskList.size(); ++i){ diskLabel = diskList.at(i); linkTarget = diskLabel.symLinkTarget(); if(linkTarget.contains(partitionName)) break; linkTarget.clear(); } if(!linkTarget.isEmpty()) tmpName = diskLabel.fileName();//可能带有乱码的名字 if(!tmpName.isEmpty()){ if(tmpName == volumeName) //ntfs、exfat格式或者非纯中文名的fat32设备,这个设备的名字不需要转码 return; else{ finalName = transcodeForGbkCode(tmpName.toLocal8Bit(), volumeName); if(!finalName.isEmpty()) volumeName = finalName; } } } QString transcodeForGbkCode(QByteArray gbkName, QString &volumeName) { int i; QByteArray dest,tmp; QString name; int len = gbkName.size(); for(i = 0x0; i < len; ++i){ if(92 == gbkName.at(i)){ if(4 == tmp.size()) dest.append(QByteArray::fromHex(tmp)); else{ if(tmp.size() > 4){ dest.append(QByteArray::fromHex(tmp.left(4))); dest.append(tmp.mid(4)); }else dest.append(tmp); } tmp.clear(); tmp.append(gbkName.at(i)); continue; }else if(tmp.size() > 0){ tmp.append(gbkName.at(i)); continue; }else dest.append(gbkName.at(i)); } if(4 == tmp.size()) dest.append(QByteArray::fromHex(tmp)); else{ if(tmp.size() > 4){ dest.append(QByteArray::fromHex(tmp.left(4))); dest.append(tmp.mid(4)); }else dest.append(tmp); } /* * gio的api获取的卷名和/dev/disk/by-label先的名字不一致,有可能是卷名 * 中含有特殊字符,导致/dev/disk/label下的卷名含有转义字符,导致二者的名字不一致 * 而不是编码格式的不一致导致的,比如卷名:“数据光盘(2020-08-22)”,在/dev/disk/by-label * 写的名字:"数据光盘\x282020-08-22\x29",经过上述处理之后可以去除转义字符,在判断一次 * 是否相等。比较完美的解决方案是找到能够判断字符串的编码格式,目前还没有找到实现方式,需要进一步完善 */ name = QString(dest); if (name == volumeName){ return name; } name = QTextCodec::codecForName("GBK")->toUnicode(dest); return name; } ukui-panel-3.0.6.4/ukui-flash-disk/device-operation.h0000644000175000017500000000400314203402514020752 0ustar fengfeng/* * Copyright (C) 2021 KylinSoft Co., Ltd. * * Authors: * Ding Jing dingjing@kylinos.cn * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include class DeviceOperation : public QObject { Q_OBJECT public: explicit DeviceOperation(GDrive* drive, QObject *parent = nullptr); explicit DeviceOperation(GVolume* volume, QObject *parent = nullptr); ~DeviceOperation(); static bool repairFilesystem(GDrive* drive); static bool repairFilesystem(GVolume* volume); static gint64 getDriveSize(GDrive* drive); static gchar* getDriveLabel(GDrive* drive); static gchar* getDriveLabel(GVolume* volume); public Q_SLOTS: void udiskFormat(QString type, QString labelName); void udiskRepair(); void udiskFormatCancel(); void udiskRepairCancel(); QString udiskSize(); QString udiskUUID(); QString udiskLabel(); private: static UDisksObject* getObjectFromBlockDevice(UDisksClient *client, const gchar *bdevice); Q_SIGNALS: void repairFinished(bool); void formatFinished(bool); private: UDisksBlock* mDiskBlock = NULL; UDisksManager* mDiskManager = NULL; UDisksFilesystem* mDiskFilesystem = NULL; GCancellable mRepairCancel; GCancellable mFormatCancel; }; #endif // DEVICEOPERATION_H ukui-panel-3.0.6.4/ukui-flash-disk/fdapplication.h0000644000175000017500000000234114203402514020335 0ustar fengfeng/* * Copyright (C) 2021 KylinSoft Co., Ltd. * * Authors: * Yang Min yangmin@kylinos.cn * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include class FDApplication : public QtSingleApplication { Q_OBJECT public: FDApplication(int &argc, char **argv); FDApplication(const QString &id, int &argc, char **argv); virtual ~FDApplication(); bool notify(QObject* obj, QEvent *event); Q_SIGNALS: void notifyWnd(QObject* obj, QEvent *event); }; #endif // __FDAPPLICATION_H__ ukui-panel-3.0.6.4/ukui-flash-disk/repair-dialog-box.cpp0000644000175000017500000017320414203402514021367 0ustar fengfeng/* * Copyright (C) 2021 KylinSoft Co., Ltd. * * Authors: * Ding Jing dingjing@kylinos.cn * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "device-manager.h" #define UDISK_DBUS_NAME "org.freedesktop.UDisks2" #define UDISK_BLOCK_DBUS_PATH "/org/freedesktop/UDisks2/block_devices/" BaseDialogStyle* BaseDialogStyle::gInstance = NULL; RepairDialogBox::RepairDialogBox(GDrive* drive, QWidget* parent) : BaseDialog(parent), mDrive(G_DRIVE(drive)) { initUI(); if (mDrive) { g_object_ref(mDrive); mDeviceName = g_drive_get_identifier (drive, G_DRIVE_IDENTIFIER_KIND_UNIX_DEVICE); } connect(mRepairBtn, &QPushButton::clicked, this, [=] (bool) { RepairProgressBar dlg(mDrive); isRunning(true); int ret = dlg.exec(); isRunning(false); if (QDialog::Accepted == ret) { accept(); } }); connect(mFormatBtn, &QPushButton::clicked, this, [=] (bool) { FormateDialog dlg(mDrive); isRunning(true); int ret = dlg.exec(); isRunning(false); if (QDialog::Accepted == ret) { accept(); } }); } RepairDialogBox::RepairDialogBox(GVolume* volume, QWidget* parent) : BaseDialog(parent), mVolume(G_VOLUME(volume)) { initUI(); if (mVolume) { g_object_ref(mVolume); mDeviceName = g_volume_get_identifier (mVolume, G_DRIVE_IDENTIFIER_KIND_UNIX_DEVICE); } connect(mRepairBtn, &QPushButton::clicked, this, [=] (bool) { RepairProgressBar dlg(mVolume, this); connect(&dlg, &RepairProgressBar::remountDevice, this, &RepairDialogBox::onRemountDevice); isRunning(true); int ret = dlg.exec(); isRunning(false); if (QDialog::Accepted == ret) { accept(); } }); connect(mFormatBtn, &QPushButton::clicked, this, [=] (bool) { FormateDialog dlg(mVolume, this); isRunning(true); int ret = dlg.exec(); isRunning(false); if (QDialog::Accepted == ret) { accept(); } }); } void RepairDialogBox::onRemountDevice() { FDVolumeInfo volumeInfo; volumeInfo.strId = mDeviceName.toStdString(); qInfo()<<"volumeId:"<setContentsMargins(0,0,0,0); QHBoxLayout* btnGroup = new QHBoxLayout; g_autofree gchar* devName = mDrive ? DeviceOperation::getDriveLabel (mDrive) : DeviceOperation::getDriveLabel (mVolume); QLabel* label = new QLabel; label->setBackgroundRole(QPalette::Base); label->setWordWrap(true); label->setTextFormat(Qt::RichText); if (devName) { label->setText(tr( "

The system could not recognize the disk contents

" "

Check that the disk/drive '%1' is properly connected," "make sure the disk is not a read-only disk, and try again." "For more information, search for help on read-only files and" "how to change read-only files.

").arg (devName)); } else { label->setText(tr( "

The system could not recognize the disk contents

" "

Check that the disk/drive is properly connected," "make sure the disk is not a read-only disk, and try again." "For more information, search for help on read-only files and" "how to change read-only files.

")); } // QScrollArea* scrollArea = new QScrollArea; // scrollArea->setContentsMargins(0, 0, 0, 0); // scrollArea->setBackgroundRole(QPalette::Base); // scrollArea->setAutoFillBackground(true); // scrollArea->setFrameStyle(0); // scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); // scrollArea->setWidget(label); mainLayout->addWidget(label, 0, 0, 6, 60, Qt::AlignTop); mFormatBtn = new QPushButton(tr("Format disk")); mRepairBtn = new QPushButton(tr("Repair")); btnGroup->addWidget(mRepairBtn); btnGroup->addWidget(mFormatBtn); mainLayout->addLayout(btnGroup, 5, 30, 1, 30); connect(this, &QDialog::finished, this, [=] () { Q_EMIT repairOK(this); deleteLater(); }); connect(this, &QDialog::accepted, this, [=] () { Q_EMIT repairOK(this); deleteLater(); }); const DeviceManager* dm = DeviceManager::getInstance(); connect(dm, &DeviceManager::driveDisconnected, this, [=] (QString device) { g_return_if_fail(false); g_return_if_fail(mDrive || mVolume); QString devName; if (mDrive) { g_autofree gchar* dev = g_drive_get_identifier(mDrive, G_DRIVE_IDENTIFIER_KIND_UNIX_DEVICE); devName = dev; } else if (mVolume) { GDrive* driv = g_volume_get_drive(mVolume); if (driv) { g_autofree gchar* dev = g_drive_get_identifier(driv, G_DRIVE_IDENTIFIER_KIND_UNIX_DEVICE); devName = dev; g_object_unref(driv); } } if (devName == device || (!device.isEmpty() && devName.isEmpty())) { accept(); } }); } void RepairDialogBox::isRunning(bool running) { if (running) { mRepairBtn->setDisabled(true); mFormatBtn->setDisabled(true); } else { mRepairBtn->setEnabled(true); mFormatBtn->setEnabled(true); } } void RepairDialogBox::drive_disconnected_callback(GVolumeMonitor* monitor, GDrive* drive, RepairDialogBox* pThis) { g_return_if_fail(drive); g_return_if_fail(!pThis->isHidden()); g_autofree gchar* tDev = nullptr; g_autofree char* devPath = g_drive_get_identifier(drive, G_DRIVE_IDENTIFIER_KIND_UNIX_DEVICE); if (devPath != NULL) { if (pThis->mVolume) { GDrive* driv = g_volume_get_drive(pThis->mVolume); if (driv) { tDev = g_drive_get_identifier(driv, G_DRIVE_IDENTIFIER_KIND_UNIX_DEVICE); g_object_unref(driv); } } else if (pThis->mDrive) { tDev = g_drive_get_identifier(pThis->mDrive, G_DRIVE_IDENTIFIER_KIND_UNIX_DEVICE); } if (tDev && 0 == g_strcmp0(tDev, devPath)) { pThis->accept(); } } Q_UNUSED(monitor) } RepairProgressBar::RepairProgressBar(GDrive* drive, QWidget *parent) : BaseDialog(parent), mDrive(G_DRIVE(drive)) { mThread = new QThread(this); mDeviceOperation = new DeviceOperation(mDrive); mDeviceOperation->moveToThread(mThread); initUI(); } RepairProgressBar::RepairProgressBar(GVolume *volume, QWidget *parent) : BaseDialog(parent), mVolume(G_VOLUME(volume)) { mThread = new QThread(this); mDeviceOperation = new DeviceOperation(mVolume); mDeviceOperation->moveToThread(mThread); initUI(); } RepairProgressBar::~RepairProgressBar() { if (mTimer) mTimer->deleteLater(); if (mProgress) mProgress->deleteLater(); if (mCancelBtn) mCancelBtn->deleteLater(); if (mDeviceOperation) mDeviceOperation->deleteLater(); } int RepairProgressBar::exec() { Q_EMIT startRepair(); return QDialog::exec(); } void RepairProgressBar::onStartRepair() { mThread->start(); mCancelBtn->setDisabled(true); mProgress->setValue(mProgress->minimum()); mTimer->start(); } void RepairProgressBar::initUI() { setAutoFillBackground(true); setWindowTitle(tr("Disk repair")); setBackgroundRole(QPalette::Base); setContentsMargins(24, 24, 24, 24); setFixedSize(mFixWidth, mFixHeight); setWindowFlags(windowFlags() & ~Qt::WindowCloseButtonHint); mTimer = new QTimer; mTimer->setInterval(1000); QGridLayout* mainLayout = new QGridLayout(this); QLabel* label = new QLabel; label->setWordWrap(true); label->setTextFormat(Qt::RichText); label->setBackgroundRole(QPalette::Base); label->setText(tr("

%1

").arg(tr("Attempting a disk repair..."))); mainLayout->addWidget(label, 1, 1, 1, 4); mProgress = new QProgressBar; mProgress->setMinimum(0); mProgress->setMaximum(1000); mainLayout->addWidget(mProgress, 2, 1, 1, 4, Qt::AlignTop); mCancelBtn = new QPushButton; mCancelBtn->setText(tr("Cancel")); mainLayout->addWidget(mCancelBtn, 3, 4, 1, 1); connect(this, &RepairProgressBar::startRepair, this, &RepairProgressBar::onStartRepair); connect(this, &RepairProgressBar::startRepair, mDeviceOperation, &DeviceOperation::udiskRepair); connect(this, &RepairProgressBar::cancel, mDeviceOperation, &DeviceOperation::udiskFormatCancel); connect(mDeviceOperation, &DeviceOperation::repairFinished, this, &RepairProgressBar::onStopRepair); connect(this, &QDialog::finished, [=] () { Q_EMIT cancel(); mTimer->stop(); mThread->exit(); }); connect(mTimer, &QTimer::timeout, this, [=] () { int val = mProgress->value(); if (val <= mProgress->maximum()) { mProgress->setValue(++val); } }); } void RepairProgressBar::onStopRepair(bool success) { mCancelBtn->setEnabled(true); mProgress->setValue(mProgress->maximum()); mTimer->stop(); mThread->exit(); if (success) { MessageBox msg(tr("Disk repair"), tr("Repair successfully!"), QMessageBox::Ok, this); msg.setPalette(getPalette()); msg.exec(); // remount device Q_EMIT remountDevice(); accept(); } else { MessageBox msg(tr("Disk repair"), tr("Repair failed. If the USB flash disk is not mounted, please try formatting the device!"), QMessageBox::Ok | QMessageBox::Cancel, this); connect(&msg, &MessageBox::format, this, [=](){ FormateDialog dlg(mDrive); int ret = dlg.exec(); if (QDialog::Accepted == ret) { accept(); } }); msg.setPalette(getPalette()); msg.exec(); reject(); } } FormateDialog::FormateDialog(GVolume* volume, QWidget *parent) : BaseDialog(parent), mVolume(volume) { mThread = new QThread; mDeviceOperation = new DeviceOperation(mVolume); mDeviceOperation->moveToThread(mThread); initUI(); } FormateDialog::~FormateDialog() { if (mTimer) mTimer->deleteLater(); if (mThread) mThread->deleteLater(); if (mNameEdit) mNameEdit->deleteLater(); if (mFSCombox) mFSCombox->deleteLater(); if (mProgress) mProgress->deleteLater(); if (mCancelBtn) mCancelBtn->deleteLater(); if (mFormatBtn) mFormatBtn->deleteLater(); if (mEraseCkbox) mEraseCkbox->deleteLater(); if (mRomSizeCombox) mRomSizeCombox->deleteLater(); if (mDeviceOperation) mDeviceOperation->deleteLater(); } FormateDialog::FormateDialog(GDrive* drive, QWidget *parent) : BaseDialog(parent), mDrive(drive) { mThread = new QThread(this); mDeviceOperation = new DeviceOperation(mDrive); mDeviceOperation->moveToThread(mThread); initUI(); } int FormateDialog::exec() { if (mDrive || mVolume) { mRomSizeCombox->clear(); mRomSizeCombox->addItem(mDeviceOperation->udiskSize()); } return QDialog::exec(); } void FormateDialog::onStopFormat(bool success) { mFormatBtn->setEnabled(true); mCancelBtn->setEnabled(true); mProgress->setValue(mProgress->maximum()); mTimer->stop(); mThread->exit(); if (success) { MessageBox msg(tr("Disk format"), tr("Formatted successfully!"), QMessageBox::Ok, this); msg.exec(); accept(); } else { MessageBox msg(tr("Disk format"), tr("Formatting failed, please unplug the U disk and try again!"), QMessageBox::Ok, this); msg.exec(); reject(); } } void FormateDialog::onStartFormat() { mProgress->setValue(mProgress->minimum()); mTimer->start(); mFormatBtn->setDisabled(true); mCancelBtn->setDisabled(true); } void FormateDialog::initUI() { setAutoFillBackground(true); setWindowTitle(tr("Format")); setBackgroundRole(QPalette::Base); setContentsMargins(24, 24, 24, 24); setFixedSize(mFixWidth, mFixHeight); setWindowIcon(QIcon::fromTheme("system-file-manager")); setWindowFlags(windowFlags() & ~Qt::WindowCloseButtonHint); QGridLayout* mainLayout = new QGridLayout(this); QLabel* romSizeLabel = new QLabel; romSizeLabel->setText(tr("Rom size:")); mRomSizeCombox = new QComboBox; mainLayout->addWidget(romSizeLabel, 1, 1, 1, 2); mainLayout->addWidget(mRomSizeCombox, 1, 3, 1, 6); QLabel* fsLabel = new QLabel; fsLabel->setText(tr("Filesystem:")); mFSCombox = new QComboBox; mFSCombox->addItem("ntfs"); mFSCombox->addItem("ext4"); mFSCombox->addItem("exfat"); mFSCombox->addItem("vfat/fat32"); mainLayout->addWidget(fsLabel, 2, 1, 1, 2); mainLayout->addWidget(mFSCombox, 2, 3, 1, 6); QLabel* uNameLabel = new QLabel; uNameLabel->setText(tr("Disk name:")); mNameEdit = new QLineEdit; mainLayout->addWidget(uNameLabel, 3, 1, 1, 2); mainLayout->addWidget(mNameEdit, 3, 3, 1, 6); QLabel* eraseLabel = new QLabel; eraseLabel->setText(tr("Completely erase(Time is longer, please confirm!)")); mEraseCkbox = new QCheckBox; mainLayout->addWidget(mEraseCkbox, 4, 1, 1, 1, Qt::AlignRight); mainLayout->addWidget(eraseLabel, 4, 2, 1, 6, Qt::AlignLeft); mProgress = new QProgressBar; mProgress->setMinimum(0); mProgress->setMaximum(1000); mainLayout->addWidget(mProgress, 5, 1, 1, 8); mCancelBtn = new QPushButton(tr("Cancel")); mFormatBtn = new QPushButton(tr("Format disk")); mainLayout->addWidget(mCancelBtn, 6, 5, 1, 2, Qt::AlignRight); mainLayout->addWidget(mFormatBtn, 6, 7, 1, 2, Qt::AlignRight); mTimer = new QTimer; mTimer->setInterval(1000); connect(mTimer, &QTimer::timeout, this, [=] () { int val = mProgress->value(); if (val <= mProgress->maximum()) { mProgress->setValue(++val); } }); connect(this, &FormateDialog::startFormat, this, &FormateDialog::onStartFormat); connect(this, &FormateDialog::startFormat, mDeviceOperation, &DeviceOperation::udiskFormat); connect(this, &FormateDialog::cancel, mDeviceOperation, &DeviceOperation::udiskFormatCancel); connect(mDeviceOperation, &DeviceOperation::formatFinished, this, &FormateDialog::onStopFormat); connect(mCancelBtn, &QPushButton::clicked, this, [=] (bool) { reject(); }); connect(this, &QDialog::finished, this, [=] () { Q_EMIT cancel(); mTimer->stop(); mThread->exit(); }); connect(mFormatBtn, &QPushButton::clicked, this, [=] (bool) { MessageBox msg(tr("Disk format"), tr("Formatting this volume will erase all data on it. Please back up all retained data before formatting. Do you want to continue?"), QMessageBox::Ok | QMessageBox::Cancel, this); if (QMessageBox::Cancel == msg.exec()) { return ; } mThread->start(); QString ctype = mFSCombox->currentText(); QString type = ctype.isEmpty() ? "vfat" : ctype; type = ("vfat/fat32" == type) ? "vfat" : type; QString dlabel = mNameEdit->text(); QString label = dlabel.isEmpty() ? mDeviceOperation->udiskLabel() : dlabel; Q_EMIT startFormat(type, label); }); } BaseDialog::BaseDialog(QWidget *parent) : QDialog(parent) { setWindowTitle(tr("Disk test")); if (QGSettings::isSchemaInstalled("org.ukui.style")) { mGSettings = new QGSettings ("org.ukui.style", "/org/ukui/style/"); connect(mGSettings, &QGSettings::changed, this, [=] (const QString &key) { if ("styleName" == key) { setStyleSheet ("QCheckBox{margin:3px;}"); QPalette p = getPalette(); for (auto obj : children ()) { if (QWidget* w = qobject_cast(obj)) { w->setPalette (p); w->update (); } } setPalette(p); update(); } }); } setTheme(); if (qgetenv ("DESKTOP_SESSION") == "ukui" && qgetenv ("XDG_SESSION_TYPE") == "x11") { setStyle (BaseDialogStyle::getStyle ()); setStyleSheet ("QCheckBox{margin:3px;}"); } } QPalette BaseDialog::getPalette() { if (mGSettings && QGSettings::isSchemaInstalled("org.ukui.style")) { QString value = mGSettings->get("styleName").toString(); if ("ukui-default" == value) { return getWhitePalette(); } else { return getBlackPalette(); } } return getWhitePalette(); } QPalette BaseDialog::getWhitePalette() { auto palette = qApp->palette(); QColor window_bg(231,231,231), window_no_bg(233,233,233), base_bg(255,255,255), base_no_bg(248, 248, 248), font_bg(0,0,0), font_br_bg(255,255,255), font_di_bg(191,191,191), button_bg(217,217,217), button_ac_bg(107,142,235), button_di_bg(233,233,233), highlight_bg(61,107,229), tip_bg(248,248,248), tip_font(22,22,22), alternateBase(248,248,248); palette.setBrush(QPalette::WindowText,font_bg); palette.setBrush(QPalette::Window,window_bg); palette.setBrush(QPalette::Active,QPalette::Window,window_bg); palette.setBrush(QPalette::Inactive,QPalette::Window,window_no_bg); palette.setBrush(QPalette::Disabled,QPalette::Window,window_no_bg); palette.setBrush(QPalette::WindowText,font_bg); palette.setBrush(QPalette::Active,QPalette::WindowText,font_bg); palette.setBrush(QPalette::Inactive,QPalette::WindowText,font_bg); palette.setBrush(QPalette::Disabled,QPalette::WindowText,font_di_bg); palette.setBrush(QPalette::Base,base_bg); palette.setBrush(QPalette::Active,QPalette::Base,base_bg); palette.setBrush(QPalette::Inactive,QPalette::Base,base_no_bg); palette.setBrush(QPalette::Disabled,QPalette::Base,base_no_bg); palette.setBrush(QPalette::Text,font_bg); palette.setBrush(QPalette::Active,QPalette::Text,font_bg); palette.setBrush(QPalette::Disabled,QPalette::Text,font_di_bg); //Cursor placeholder #if (QT_VERSION >= QT_VERSION_CHECK(5,12,0)) palette.setBrush(QPalette::PlaceholderText,font_di_bg); #endif palette.setBrush(QPalette::ToolTipBase,tip_bg); palette.setBrush(QPalette::ToolTipText,tip_font); palette.setBrush(QPalette::Highlight,highlight_bg); palette.setBrush(QPalette::Active,QPalette::Highlight,highlight_bg); palette.setBrush(QPalette::HighlightedText,font_br_bg); palette.setBrush(QPalette::BrightText,font_br_bg); palette.setBrush(QPalette::Active,QPalette::BrightText,font_br_bg); palette.setBrush(QPalette::Inactive,QPalette::BrightText,font_br_bg); palette.setBrush(QPalette::Disabled,QPalette::BrightText,font_di_bg); palette.setBrush(QPalette::Button,button_bg); palette.setBrush(QPalette::Active,QPalette::Button,button_bg); palette.setBrush(QPalette::Inactive,QPalette::Button,button_bg); palette.setBrush(QPalette::Disabled,QPalette::Button,button_di_bg); palette.setBrush(QPalette::ButtonText,font_bg); palette.setBrush(QPalette::Inactive,QPalette::ButtonText,font_bg); palette.setBrush(QPalette::Disabled,QPalette::ButtonText,font_di_bg); palette.setBrush(QPalette::AlternateBase,alternateBase); palette.setBrush(QPalette::Inactive,QPalette::AlternateBase,alternateBase); palette.setBrush(QPalette::Disabled,QPalette::AlternateBase,button_di_bg); return palette; } QPalette BaseDialog::getBlackPalette() { auto palette = qApp->palette(); QColor window_bg(45,46,50), window_no_bg(48,46,50), base_bg(31,32,34), base_no_bg(28,28,30), font_bg(255,255,255), font_br_bg(255,255,255), font_di_bg(255,255,255), button_bg(61,61,65), button_ac_bg(48,48,51), button_di_bg(48,48,51), highlight_bg(61,107,229), tip_bg(61,61,65), tip_font(232,232,232), alternateBase(36,35,40); font_bg.setAlphaF(0.9); font_br_bg.setAlphaF(0.9); font_di_bg.setAlphaF(0.1); palette.setBrush(QPalette::Window,window_bg); palette.setBrush(QPalette::Active,QPalette::Window,window_bg); palette.setBrush(QPalette::Inactive,QPalette::Window,window_no_bg); palette.setBrush(QPalette::Disabled,QPalette::Window,window_no_bg); palette.setBrush(QPalette::WindowText,font_bg); palette.setBrush(QPalette::Active,QPalette::WindowText,font_bg); palette.setBrush(QPalette::Inactive,QPalette::WindowText,font_bg); palette.setBrush(QPalette::Disabled,QPalette::WindowText,font_di_bg); palette.setBrush(QPalette::Base,base_bg); palette.setBrush(QPalette::Active,QPalette::Base,base_bg); palette.setBrush(QPalette::Inactive,QPalette::Base,base_no_bg); palette.setBrush(QPalette::Disabled,QPalette::Base,base_no_bg); palette.setBrush(QPalette::Text,font_bg); palette.setBrush(QPalette::Active,QPalette::Text,font_bg); palette.setBrush(QPalette::Disabled,QPalette::Text,font_di_bg); //Cursor placeholder #if (QT_VERSION >= QT_VERSION_CHECK(5,12,0)) palette.setBrush(QPalette::PlaceholderText,font_di_bg); #endif palette.setBrush(QPalette::ToolTipBase,tip_bg); palette.setBrush(QPalette::ToolTipText,tip_font); palette.setBrush(QPalette::Highlight,highlight_bg); palette.setBrush(QPalette::Active,QPalette::Highlight,highlight_bg); palette.setBrush(QPalette::HighlightedText,font_br_bg); palette.setBrush(QPalette::BrightText,font_br_bg); palette.setBrush(QPalette::Active,QPalette::BrightText,font_br_bg); palette.setBrush(QPalette::Inactive,QPalette::BrightText,font_br_bg); palette.setBrush(QPalette::Disabled,QPalette::BrightText,font_di_bg); palette.setBrush(QPalette::Button,button_bg); palette.setBrush(QPalette::Active,QPalette::Button,button_bg); palette.setBrush(QPalette::Inactive,QPalette::Button,button_bg); palette.setBrush(QPalette::Disabled,QPalette::Button,button_di_bg); palette.setBrush(QPalette::ButtonText,font_bg); palette.setBrush(QPalette::Inactive,QPalette::ButtonText,font_bg); palette.setBrush(QPalette::Disabled,QPalette::ButtonText,font_di_bg); palette.setBrush(QPalette::AlternateBase,alternateBase); palette.setBrush(QPalette::Inactive,QPalette::AlternateBase,alternateBase); palette.setBrush(QPalette::Disabled,QPalette::AlternateBase,button_di_bg); return palette; } void BaseDialog::setTheme() { setPalette(getPalette()); } MessageBox::MessageBox(QString title, QString text, QMessageBox::StandardButtons bt, QWidget *parent) : BaseDialog(parent) { setFixedSize(420, 200); setContentsMargins(24, 24, 24, 24); setAutoFillBackground(true); setWindowTitle(title); setBackgroundRole(QPalette::Base); QGridLayout* mainLayout = new QGridLayout(this); QLabel* label = new QLabel; label->setText(text); label->setWordWrap(true); mainLayout->addWidget(label, 1, 1, 1, 4); QPushButton* ok = nullptr; QPushButton* cancel = nullptr; if (bt & QMessageBox::Ok && bt & QMessageBox::Cancel) { ok = new QPushButton; ok->setText(tr("Format")); mainLayout->addWidget(ok, 2, 3, 1, 1); cancel = new QPushButton; cancel->setText(tr("Cancel")); mainLayout->addWidget(cancel, 2, 4, 1, 1); } else if (bt & QMessageBox::Ok && !(bt & QMessageBox::Cancel)) { ok = new QPushButton; ok->setText(tr("OK")); mainLayout->addWidget(ok, 2, 4, 1, 1); } else if (!(bt & QMessageBox::Ok) && bt & QMessageBox::Cancel) { cancel = new QPushButton; cancel->setText(tr("Cancel")); mainLayout->addWidget(cancel, 2, 4, 1, 1); } if (ok) { connect(ok, &QPushButton::clicked, this, [=] (bool) { Q_EMIT format(); done(QMessageBox::Ok); }); } if (cancel) { connect(cancel, &QPushButton::clicked, this, [=] (bool) { done(QMessageBox::Cancel); }); } } BaseDialogStyle::BaseDialogStyle() { } BaseDialogStyle::~BaseDialogStyle() { } BaseDialogStyle *BaseDialogStyle::getStyle() { if (!gInstance) { gInstance = new BaseDialogStyle; } return gInstance; } void BaseDialogStyle::polish(QWidget *w) { if (BaseDialog* wi = qobject_cast(w)) { mPalette = wi->getPalette (); } if (w) w->setPalette (mPalette); } void BaseDialogStyle::drawControl(QStyle::ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const { switch (element) { case CE_ComboBoxLabel: { if (const QStyleOptionComboBox *comboBox = qstyleoption_cast(option)) { QRect arrowRect = QProxyStyle::subControlRect(CC_ComboBox, comboBox, SC_ComboBoxArrow, widget); QRect editRect = QProxyStyle::subControlRect(CC_ComboBox, comboBox, SC_ComboBoxEditField, widget); QStyleOption arrow = *option; arrow.state = option->state & State_Enabled ? State_Enabled : State_None; arrow.rect = arrowRect; arrow.palette = mPalette; QProxyStyle::drawPrimitive(PE_IndicatorArrowDown, &arrow, painter, widget); painter->save(); if (!comboBox->currentText.isEmpty() && !comboBox->editable) { drawItemText(painter, editRect, visualAlignment(option->direction, Qt::AlignLeft | Qt::AlignVCenter), mPalette, option->state & State_Enabled, comboBox->currentText); } painter->restore(); return; } } break; case CE_PushButton: { if (const QStyleOptionButton *button = qstyleoption_cast(option)) { drawControl(CE_PushButtonBevel, option, painter, widget); QStyleOptionButton subopt = *button; subopt.rect = QProxyStyle::subElementRect(SE_PushButtonContents, option, widget); subopt.palette = mPalette; drawControl(CE_PushButtonLabel, &subopt, painter, widget); return; } } break; case CE_PushButtonBevel: { drawPrimitive(PE_PanelButtonCommand, option, painter, widget); } break; case CE_PushButtonLabel: { if (const QStyleOptionButton *button = qstyleoption_cast(option)) { const bool enable = button->state & State_Enabled; const bool text = !button->text.isEmpty(); const bool icon = !button->icon.isNull(); bool isWindowButton = false; bool isWindowColoseButton = false; bool isImportant = false; bool useButtonPalette = false; if (widget) { if (widget->property("isWindowButton").isValid()) { if (widget->property("isWindowButton").toInt() == 0x01) isWindowButton = true; if (widget->property("isWindowButton").toInt() == 0x02) isWindowColoseButton = true; } if (widget->property("isImportant").isValid()) isImportant = widget->property("isImportant").toBool(); if (widget->property("useButtonPalette").isValid()) useButtonPalette = widget->property("useButtonPalette").toBool(); } QRect drawRect = button->rect; int spacing = 8; QStyleOption sub = *option; if (isImportant && !(button->features & QStyleOptionButton::Flat)) { sub.state = option->state | State_On; } else if (isWindowButton || useButtonPalette) { sub.state = enable ? State_Enabled : State_None; } else { sub.state = option->state; } if (button->features & QStyleOptionButton::HasMenu) { QRect arrowRect; int indicator = proxy()->pixelMetric(PM_MenuButtonIndicator, option, widget); arrowRect.setRect(drawRect.right() - indicator, drawRect.top() + (drawRect.height() - indicator) / 2, indicator, indicator); arrowRect = visualRect(option->direction, option->rect, arrowRect); if (!text && !icon) spacing = 0; drawRect.setWidth(drawRect.width() - indicator - spacing); drawRect = visualRect(button->direction, button->rect, drawRect); sub.rect = arrowRect; QProxyStyle::drawPrimitive(PE_IndicatorArrowDown, &sub, painter, widget); } int tf = Qt::AlignCenter; if (QProxyStyle::styleHint(SH_UnderlineShortcut, button, widget)) { tf |= Qt::TextShowMnemonic; } QPixmap pixmap; if (icon) { QIcon::Mode mode = button->state & State_Enabled ? QIcon::Normal : QIcon::Disabled; if (mode == QIcon::Normal && button->state & State_HasFocus) mode = QIcon::Active; QIcon::State state = QIcon::Off; if (button->state & State_On) state = QIcon::On; pixmap = button->icon.pixmap(button->iconSize, mode, state); } QFontMetrics fm = button->fontMetrics; int textWidth = fm.boundingRect(option->rect, tf, button->text).width() + 2; int iconWidth = icon ? button->iconSize.width() : 0; QRect iconRect, textRect; if (icon && text) { int width = textWidth + spacing + iconWidth; if (width > drawRect.width()) { width = drawRect.width(); textWidth = width - spacing - iconWidth; } textRect.setRect(drawRect.x(), drawRect.y(), width, drawRect.height()); textRect.moveCenter(drawRect.center()); iconRect.setRect(textRect.left(), textRect.top(), iconWidth, textRect.height()); textRect.setRect(iconRect.right() + spacing + 1, textRect.y(), textWidth, textRect.height()); iconRect = visualRect(option->direction, drawRect, iconRect); textRect = visualRect(option->direction, drawRect, textRect); } else if (icon) { iconRect = drawRect; } else if (text) { textRect = drawRect; } if (textRect.isValid()) { if (enable) { if (isWindowButton || useButtonPalette) { drawItemText(painter, textRect, tf, button->palette, true, button->text, mPalette.ButtonText); } else { if (isImportant) { if (button->features & QStyleOptionButton::Flat) { drawItemText(painter, textRect, tf, mPalette, true, button->text, mPalette.ButtonText); } else { drawItemText(painter, textRect, tf, mPalette, true, button->text, mPalette.HighlightedText); } if (button->state & (State_MouseOver | State_Sunken | State_On)) { drawItemText(painter, textRect, tf, mPalette, true, button->text, mPalette.HighlightedText); } } else { if (button->state & (State_MouseOver | State_Sunken | State_On)) { drawItemText(painter, textRect, tf, mPalette, true, button->text, mPalette.HighlightedText); } else { drawItemText(painter, textRect, tf, mPalette, true, button->text, mPalette.ButtonText); } } } } else { drawItemText(painter, textRect, tf, mPalette, false, button->text, mPalette.ButtonText); } } return; } } break; case CE_CheckBox: { if (const QStyleOptionButton *button = qstyleoption_cast(option)) { QStyleOptionButton subopt = *button; subopt.palette = mPalette; subopt.rect = QProxyStyle::subElementRect(SE_CheckBoxIndicator, option, widget); drawPrimitive(PE_IndicatorCheckBox, &subopt, painter, widget); subopt.rect = QProxyStyle::subElementRect(SE_CheckBoxContents, option, widget); drawControl(CE_CheckBoxLabel, &subopt, painter, widget); return; } } break; case CE_RadioButtonLabel: case CE_CheckBoxLabel: { if (const QStyleOptionButton *button = qstyleoption_cast(option)) { uint alignment = visualAlignment(button->direction, Qt::AlignLeft | Qt::AlignVCenter); const bool enable = button->state & State_Enabled; if (!proxy()->styleHint(SH_UnderlineShortcut, button, widget)) alignment |= Qt::TextHideMnemonic; QPixmap pixmap; QRect textRect = button->rect; if (!button->icon.isNull()) { pixmap = button->icon.pixmap(button->iconSize, enable ? QIcon::Normal : QIcon::Disabled); drawItemPixmap(painter, button->rect, alignment, pixmap); int spacing = 8; if (button->direction == Qt::RightToLeft) textRect.setRight(textRect.right() - button->iconSize.width() - spacing); else textRect.setLeft(textRect.left() + button->iconSize.width() + spacing); } if (!button->text.isEmpty()){ drawItemText(painter, textRect, alignment | Qt::TextShowMnemonic, mPalette, button->state & State_Enabled, button->text, mPalette.WindowText); } return; } } break; case CE_MenuItem: break; /* 进度条 */ case CE_ProgressBar: { if (const QStyleOptionProgressBar *pb = qstyleoption_cast(option)) { QStyleOptionProgressBar subOption = *pb; subOption.palette = mPalette; subOption.rect = proxy()->subElementRect(SE_ProgressBarGroove, pb, widget); proxy()->drawControl(CE_ProgressBarGroove, &subOption, painter, widget); subOption.rect = proxy()->subElementRect(SE_ProgressBarContents, pb, widget); proxy()->drawControl(CE_ProgressBarContents, &subOption, painter, widget); if (pb->textVisible) { subOption.rect = proxy()->subElementRect(SE_ProgressBarLabel, pb, widget); proxy()->drawControl(CE_ProgressBarLabel, &subOption, painter, widget); } return; } break; } case CE_ProgressBarGroove: { const bool enable = option->state & State_Enabled; painter->save(); painter->setPen(Qt::NoPen); painter->setBrush(mPalette.brush(enable ? mPalette.Active : mPalette.Disabled, mPalette.Button)); painter->drawRoundedRect(option->rect, 4, 4); painter->restore(); return; } case CE_ProgressBarContents: { if (const QStyleOptionProgressBar *pb = qstyleoption_cast(option)) { const auto progress = qMax(pb->progress, pb->minimum); if (progress == pb->minimum) return; const bool vertical = pb->orientation == Qt::Vertical; const bool inverted = pb->invertedAppearance; const bool indeterminate = (pb->minimum == 0 && pb->maximum == 0); QRect rect = pb->rect; int maxWidth = vertical ? pb->rect.height() : pb->rect.width(); const auto totalSteps = qMax(Q_INT64_C(1), qint64(pb->maximum) - pb->minimum); const auto progressSteps = qint64(progress) - pb->minimum; const auto progressBarWidth = progressSteps * maxWidth / totalSteps; int len = indeterminate ? maxWidth : progressBarWidth; bool reverse = (!vertical && (pb->direction == Qt::RightToLeft)) || vertical; if (inverted) reverse = !reverse; QColor startColor = mPalette.color(mPalette.Active, mPalette.Highlight); QColor endColor = mPalette.color(mPalette.Active, mPalette.Highlight); QLinearGradient linearGradient; linearGradient.setColorAt(0, startColor); linearGradient.setColorAt(1, endColor); QRect progressRect; if (indeterminate) { } else { if (vertical) { if (reverse) { progressRect.setRect(rect.left(), rect.bottom() + 1 - len, rect.width(), len); linearGradient.setStart(progressRect.bottomLeft()); linearGradient.setFinalStop(progressRect.topLeft()); } else { progressRect.setRect(rect.x(), rect.top(), rect.width(), len); linearGradient.setStart(progressRect.topLeft()); linearGradient.setFinalStop(progressRect.bottomLeft()); } } else { if (reverse) { progressRect.setRect(rect.right() + 1 - len, rect.top(), len, rect.height()); linearGradient.setStart(progressRect.topRight()); linearGradient.setFinalStop(progressRect.topLeft()); } else { progressRect.setRect(rect.x(), rect.y(), len, rect.height()); linearGradient.setStart(progressRect.topLeft()); linearGradient.setFinalStop(progressRect.topRight()); } } } painter->save(); painter->setPen(Qt::NoPen); painter->setBrush(linearGradient); painter->setRenderHint(QPainter::Antialiasing, true); painter->drawRoundedRect(progressRect, 4, 4); painter->restore(); return; } } break; case CE_ProgressBarLabel: { if (const QStyleOptionProgressBar *pb = qstyleoption_cast(option)) { if (pb->textVisible) { const auto progress = qMax(pb->progress, pb->minimum); const bool vertical = pb->orientation == Qt::Vertical; const bool inverted = pb->invertedAppearance; const bool indeterminate = (pb->minimum == 0 && pb->maximum == 0); int maxWidth = vertical ? pb->rect.height() : pb->rect.width(); const auto totalSteps = qMax(Q_INT64_C(1), qint64(pb->maximum) - pb->minimum); const auto progressSteps = qint64(progress) - pb->minimum; const auto progressBarWidth = progressSteps * maxWidth / totalSteps; int len = indeterminate ? maxWidth : progressBarWidth; bool reverse = (!vertical && (pb->direction == Qt::RightToLeft)) || vertical; if (inverted) reverse = !reverse; painter->save(); painter->setBrush(Qt::NoBrush); QRect rect = pb->rect; if (pb->orientation == Qt::Vertical) { rect.setRect(rect.y(), rect.x(), rect.height(), rect.width()); QTransform m; m.rotate(90); m.translate(0, -rect.height()); painter->setTransform(m, true); } QRect textRect(rect.x(), rect.y(), pb->fontMetrics.horizontalAdvance(pb->text), rect.height()); textRect.moveCenter(rect.center()); if (len <= textRect.left()) { painter->setPen(mPalette.color(mPalette.Active, mPalette.WindowText)); painter->drawText(textRect, pb->text, QTextOption(Qt::AlignAbsolute | Qt::AlignHCenter | Qt::AlignVCenter)); } else if (len >= textRect.right()) { painter->setPen(mPalette.color(mPalette.Active, mPalette.HighlightedText)); painter->drawText(textRect, pb->text, QTextOption(Qt::AlignAbsolute | Qt::AlignHCenter | Qt::AlignVCenter)); } else { QRect leftRect(textRect.x(), textRect.y(), len - textRect.left(), textRect.height()); QRect rightRect(leftRect.right() + 1, textRect.y(), textRect.right() + 1 - len, textRect.height()); if (reverse) { leftRect.setRect(textRect.left(), textRect.top(), maxWidth - len - textRect.left(), textRect.height()); rightRect.setRect(leftRect.right() + 1, textRect.top(), textRect.width() - leftRect.width(), textRect.height()); painter->setPen(mPalette.color(mPalette.Active, mPalette.HighlightedText)); painter->setClipRect(rightRect); painter->drawText(textRect, pb->text, QTextOption(Qt::AlignAbsolute | Qt::AlignHCenter | Qt::AlignVCenter)); painter->setPen(mPalette.color(mPalette.Active, mPalette.WindowText)); painter->setClipRect(leftRect); painter->drawText(textRect, pb->text, QTextOption(Qt::AlignAbsolute | Qt::AlignHCenter | Qt::AlignVCenter)); } else { painter->setPen(mPalette.color(mPalette.Active, mPalette.WindowText)); painter->setClipRect(rightRect); painter->drawText(textRect, pb->text, QTextOption(Qt::AlignAbsolute | Qt::AlignHCenter | Qt::AlignVCenter)); painter->setPen(mPalette.color(mPalette.Active, mPalette.HighlightedText)); painter->setClipRect(leftRect); painter->drawText(textRect, pb->text, QTextOption(Qt::AlignAbsolute | Qt::AlignHCenter | Qt::AlignVCenter)); } } painter->resetTransform(); painter->restore(); } return; } } break; default: QStyleOption opt = *option; opt.palette = mPalette; QProxyStyle::drawControl (element, &opt, painter, widget); break; } QProxyStyle::drawControl (element, option, painter, widget); } void BaseDialogStyle::drawPrimitive(PrimitiveElement elem, const QStyleOption *option, QPainter *painter, const QWidget *widget) const { switch (elem) { case PE_PanelButtonTool: { QProxyStyle::drawPrimitive (elem, option, painter, widget); return; bool isWindowColoseButton = false; bool isWindowButton = false; bool useButtonPalette = false; if (widget) { if (widget->property("isWindowButton").isValid()) { if (widget->property("isWindowButton").toInt() == 0x01) isWindowButton = true; if (widget->property("isWindowButton").toInt() == 0x02) isWindowColoseButton = true; } if (widget->property("useButtonPalette").isValid()) useButtonPalette = widget->property("useButtonPalette").toBool(); } const bool enable = option->state & State_Enabled; const bool raise = option->state & State_AutoRaise; const bool sunken = option->state & State_Sunken; const bool hover = option->state & State_MouseOver; const bool on = option->state & State_On; if (!enable) { painter->save(); painter->setPen(Qt::NoPen); if (on) painter->setBrush(mPalette.color(mPalette.Disabled, mPalette.Button)); else if (raise) painter->setBrush(Qt::NoBrush); else painter->setBrush(mPalette.color(mPalette.Disabled, mPalette.Button)); painter->setRenderHint(QPainter::Antialiasing, true); painter->drawRoundedRect(option->rect, 4, 4); painter->restore(); return; } if (!raise) { painter->save(); painter->setPen(Qt::NoPen); painter->setBrush(mPalette.color(mPalette.Active, mPalette.Button)); painter->setRenderHint(QPainter::Antialiasing, true); painter->drawRoundedRect(option->rect, 4, 4); painter->restore(); } painter->save(); painter->setRenderHint(QPainter::Antialiasing, true); painter->setPen(Qt::NoPen); if (sunken || on) { if (isWindowButton) { QColor color = mPalette.color(mPalette.Active, mPalette.Base); color.setAlphaF(0.15); painter->setBrush(color); } else if (isWindowColoseButton) { painter->setBrush(QColor("#E44C50")); } else { painter->setBrush(mPalette.brush (mPalette.Active, mPalette.Highlight)); } } else if (hover) { if (isWindowButton) { QColor color = mPalette.color(mPalette.Active, mPalette.Base); color.setAlphaF(0.1); painter->setBrush(color); } else if (isWindowColoseButton) { painter->setBrush(QColor("#F86458")); } else { painter->setBrush(mPalette.brush (mPalette.Active, mPalette.Highlight)); } } painter->drawRoundedRect(option->rect, 4, 4); painter->restore(); return; return; } break; case PE_PanelButtonCommand: { if (const QStyleOptionButton *button = qstyleoption_cast(option)) { const bool enable = button->state & State_Enabled; const bool hover = button->state & State_MouseOver; const bool sunken = button->state & State_Sunken; const bool on = button->state & State_On; qreal x_Radius = 4; qreal y_Radius = 4; bool isWindowButton = false; bool isWindowColoseButton = false; bool isImportant = false; bool useButtonPalette = false; if (widget) { if (widget->property("isWindowButton").isValid()) { if (widget->property("isWindowButton").toInt() == 0x01) isWindowButton = true; if (widget->property("isWindowButton").toInt() == 0x02) isWindowColoseButton = true; } if (widget->property("isImportant").isValid()) isImportant = widget->property("isImportant").toBool(); if (widget->property("useButtonPalette").isValid()) useButtonPalette = widget->property("useButtonPalette").toBool(); if (qobject_cast(widget) || qobject_cast(widget) || qobject_cast(widget)) useButtonPalette = true; } if (!enable) { painter->save(); painter->setPen(Qt::NoPen); if (on) { painter->setBrush(Qt::NoBrush); } else if (button->features & QStyleOptionButton::Flat) { painter->setBrush(Qt::NoBrush); } else { painter->setBrush(mPalette.brush(mPalette.Disabled, mPalette.Button)); } painter->setRenderHint(QPainter::Antialiasing, true); painter->drawRoundedRect(option->rect, x_Radius, y_Radius); painter->restore(); return; } if (!(button->features & QStyleOptionButton::Flat)) { painter->save(); painter->setPen(Qt::NoPen); if (isImportant) painter->setBrush(mPalette.brush(mPalette.Active, mPalette.Highlight)); else painter->setBrush(mPalette.brush(mPalette.Active, mPalette.Button)); painter->setRenderHint(QPainter::Antialiasing, true); painter->drawRoundedRect(option->rect, x_Radius, y_Radius); painter->restore(); } painter->save(); painter->setRenderHint(QPainter::Antialiasing,true); painter->setPen(Qt::NoPen); if (sunken || on) { if (isWindowColoseButton) { painter->setBrush(QColor("#E44C50")); } else { painter->setBrush(mPalette.brush (mPalette.Active, mPalette.Highlight)); } } else if (hover) { if (isWindowColoseButton) { painter->setBrush(QColor("#F86458")); } else { painter->setBrush(mPalette.brush (mPalette.Active, mPalette.Highlight)); } } painter->drawRoundedRect(button->rect, x_Radius, y_Radius); painter->restore(); return; } } break; case PE_IndicatorCheckBox: { if (const QStyleOptionButton *checkbox = qstyleoption_cast(option)) { const bool useDarkPalette = false; bool enable = checkbox->state & State_Enabled; bool mouseOver = checkbox->state & State_MouseOver; bool sunKen = checkbox->state & State_Sunken; bool on = checkbox->state & State_On; bool noChange = checkbox->state & State_NoChange; QRectF rect = checkbox->rect; int width = rect.width(); int heigth = rect.height(); int x_Radius = 4; int y_Radius = 4; QPainterPath path; if (on) { path.moveTo(width/4 + checkbox->rect.left(), heigth/2 + checkbox->rect.top()); path.lineTo(width*0.45 + checkbox->rect.left(), heigth*3/4 + checkbox->rect.top()); path.lineTo(width*3/4 + checkbox->rect.left(), heigth/4 + checkbox->rect.top()); } else if (noChange){ path.moveTo(rect.left() + width/4, rect.center().y()); path.lineTo(rect.right() - width/4 , rect.center().y()); } painter->save(); painter->setClipRect(rect); painter->setRenderHint(QPainter::Antialiasing, true); if (enable) { if (on | noChange) { if (sunKen) { painter->setPen(QColor(25, 101, 207)); painter->setBrush(mPalette.brush(mPalette.Active, mPalette.Highlight)); } else if (mouseOver) { painter->setPen(QColor(36, 109, 212)); painter->setBrush(mPalette.brush(mPalette.Active, mPalette.Highlight)); } else { painter->setPen(QColor(36, 109, 212)); painter->setBrush(mPalette.brush(mPalette.Active, mPalette.Highlight)); } painter->drawRoundedRect(rect, x_Radius, y_Radius); painter->setPen(QPen(mPalette.brush(mPalette.Active, mPalette.HighlightedText), 2, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); painter->setBrush(Qt::NoBrush); painter->drawPath(path); } else { if (sunKen) { if (useDarkPalette) { painter->setPen(QColor(36, 109, 212)); painter->setBrush(QColor(6, 35, 97)); } else { painter->setPen(QColor(36, 109, 212)); painter->setBrush(QColor(179, 221, 255)); } } else if (mouseOver) { if (useDarkPalette) { painter->setPen(QColor(55, 144, 250)); painter->setBrush(QColor(9, 53, 153)); } else { painter->setPen(QColor(97, 173, 255)); painter->setBrush(QColor(219, 240, 255)); } } else { if (useDarkPalette) { painter->setPen(QColor(72, 72, 77)); painter->setBrush(QColor(48, 48, 51)); } else { painter->setPen(QColor(191, 191, 191)); painter->setBrush(mPalette.color(mPalette.Active, mPalette.Window)); } } painter->drawRoundedRect(rect, x_Radius, y_Radius); } } else { if (useDarkPalette) { painter->setPen(QColor(48, 48, 51)); painter->setBrush(QColor(28, 28, 30)); } else { painter->setPen(QColor(224, 224, 224)); painter->setBrush(QColor(233, 233, 233)); } painter->drawRoundedRect(rect, x_Radius, y_Radius); if (on | noChange) { painter->setPen(QPen(mPalette.brush(mPalette.Disabled, mPalette.ButtonText), 2, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); painter->setBrush(Qt::NoBrush); painter->drawPath(path); } } painter->restore(); return; } } break; case PE_PanelLineEdit: { if (widget) { if (QAction *clearAction = widget->findChild(QLatin1String("_q_qlineeditclearaction"))) { QStyleOption subOption = *option; subOption.palette = mPalette; QColor color = subOption.palette.color(QPalette::Text); color.setAlphaF(1.0); subOption.palette.setColor(QPalette::Text, color); } } if (widget) { if (widget->parentWidget()) if (widget->parentWidget()->inherits("QDoubleSpinBox")|| widget->parentWidget()->inherits("QSpinBox") || widget->parentWidget()->inherits("QComboBox") || widget->parentWidget()->inherits("QDateTimeEdit")) { return; } } if (const QStyleOptionFrame *f = qstyleoption_cast(option)) { const bool enable = f->state & State_Enabled; const bool focus = f->state & State_HasFocus; if (!enable) { painter->save(); painter->setPen(Qt::NoPen); painter->setBrush(mPalette.brush(mPalette.Disabled, mPalette.Button)); painter->setRenderHint(QPainter::Antialiasing, true); painter->drawRoundedRect(option->rect, 4, 4); painter->restore(); return; } if (f->state & State_ReadOnly) { painter->save(); painter->setPen(Qt::NoPen); painter->setBrush(mPalette.brush(mPalette.Active, mPalette.Button)); painter->setRenderHint(QPainter::Antialiasing, true); painter->drawRoundedRect(option->rect, 4, 4); painter->restore(); return; } if (focus) { painter->save(); painter->setPen(QPen(mPalette.brush(mPalette.Active, mPalette.Highlight), 2, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); painter->setBrush(mPalette.brush(mPalette.Active, mPalette.Base)); painter->setRenderHint(QPainter::Antialiasing, true); painter->drawRoundedRect(option->rect.adjusted(1, 1, -1, -1), 4, 4); painter->restore(); } else { QStyleOptionButton button; button.state = option->state & ~(State_Sunken | State_On); button.palette = mPalette; button.rect = option->rect; drawPrimitive(PE_PanelButtonCommand, &button, painter, widget); if (f->state & State_MouseOver) { QRectF rect = f->rect; painter->save(); painter->setPen(QPen(mPalette.brush(mPalette.Active, mPalette.Highlight), 1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); painter->setBrush(Qt::NoBrush); painter->setRenderHint(QPainter::Antialiasing, true); painter->drawRoundedRect(rect.adjusted(0.5, 0.5, -0.5, -0.5), 4, 4); painter->restore(); } } return; } } break; default: QStyleOption opt = *option; opt.palette = mPalette; QProxyStyle::drawPrimitive (elem, &opt, painter, widget); break; } } void BaseDialogStyle::drawItemText(QPainter *painter, const QRect &rect, int flags, const QPalette &pal, bool enabled, const QString &text, QPalette::ColorRole textRole) const { QProxyStyle::drawItemText (painter, rect, flags, mPalette, enabled, text, textRole); } void BaseDialogStyle::drawComplexControl(ComplexControl control, const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget) const { switch (control) { case CC_ComboBox: { if (const QStyleOptionComboBox *comboBox = qstyleoption_cast(option)) { const bool enable = comboBox->state & State_Enabled; const bool on = comboBox->state & State_On; const bool hover = comboBox->state & State_MouseOver; if (!enable) { painter->save(); painter->setPen(Qt::NoPen); painter->setBrush(mPalette.brush(mPalette.Disabled, mPalette.Button)); painter->setRenderHint(QPainter::Antialiasing,true); painter->drawRoundedRect(option->rect, 4, 4); painter->restore(); return; } if (comboBox->editable) { painter->save(); if (comboBox->state & (State_HasFocus | State_On)) { painter->setPen(QPen(mPalette.brush(mPalette.Active, mPalette.Highlight), 2, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); painter->setBrush(mPalette.brush(mPalette.Active, mPalette.Base)); } else { painter->setPen(Qt::NoPen); painter->setBrush(mPalette.brush(mPalette.Active, mPalette.Button)); } painter->setRenderHint(QPainter::Antialiasing,true); painter->drawRoundedRect(option->rect.adjusted(1, 1, -1, -1), 4, 4); painter->restore(); } else { QStyleOptionButton button; button.state = option->state; button.rect = option->rect; button.palette = mPalette; drawPrimitive(PE_PanelButtonCommand, &button, painter, widget); if (on) { painter->save(); painter->setPen(QPen(mPalette.brush(mPalette.Active, mPalette.Highlight), 2, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); painter->setBrush(Qt::NoBrush); painter->setRenderHint(QPainter::Antialiasing,true); painter->drawRoundedRect(option->rect.adjusted(1, 1, -1, -1), 4, 4); painter->restore(); } } if (hover) { QRectF rect = comboBox->rect; painter->save(); painter->setPen(QPen(mPalette.brush(mPalette.Active, mPalette.Highlight), 1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); painter->setBrush(Qt::NoBrush); painter->setRenderHint(QPainter::Antialiasing,true); painter->drawRoundedRect(rect.adjusted(0.5, 0.5, -0.5, -0.5), 4, 4); painter->restore(); } return; } break; } default: QStyleOptionComplex opt = *option; opt.palette = mPalette; QProxyStyle::drawComplexControl (control, &opt, painter, widget); break; } } ukui-panel-3.0.6.4/ukui-flash-disk/MacroFile.h0000644000175000017500000000322314203402514017361 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "MacroFile.h" #include "UnionVariable.h" QT_BEGIN_NAMESPACE namespace Ui { class ejectInterface; } QT_END_NAMESPACE class ejectInterface : public QWidget { Q_OBJECT public: ejectInterface(QWidget *parent,QString name,int typeDevice,QString strDevId); ~ejectInterface(); int getPanelPosition(QString str); int getPanelHeight(QString str); void initTransparentState(); void getTransparentData(); void initFontSetting(); void getFontSize(); private: QLabel *eject_image_label; QIcon eject_image_icon; QLabel *show_text_label; QLabel *mount_name_label; QHBoxLayout *ejectinterface_h_BoxLayout; QHBoxLayout *mountname_h_BoxLayout; QVBoxLayout *main_V_BoxLayput; QTimer *interfaceHideTime; QScreen *EjectScreen; double m_transparency; int fontSize; QGSettings *m_transparency_gsettings = nullptr; QGSettings *fontSettings = nullptr; private Q_SLOTS: void on_interface_hide(); protected: void paintEvent(QPaintEvent *event); private: void moveEjectInterfaceRight(); }; #endif ukui-panel-3.0.6.4/ukui-flash-disk/clickLabel.h0000644000175000017500000000217114203402514017546 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include class ClickLabel : public QLabel { Q_OBJECT public: explicit ClickLabel(QWidget *parent = 0); ~ClickLabel(); protected: void mousePressEvent(QMouseEvent * event); //virtual void paintEvent(QPaintEvent * event); Q_SIGNALS: void clicked(); }; #endif // CLICKLABEL_H ukui-panel-3.0.6.4/ukui-flash-disk/fdclickwidget.h0000644000175000017500000000665214203402514020334 0ustar fengfeng/* * Copyright (C) 2021 KylinSoft Co., Ltd. * * Authors: * Yang Min yangmin@kylinos.cn * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include #include #include #include #include #include #include #include #include "ejectInterface.h" #include "clickLabel.h" #include "UnionVariable.h" #include "interactivedialog.h" #include "gpartedinterface.h" typedef struct _EjectDeviceInfo_s { void* pVoid = nullptr; QString strDriveId = ""; QString strDriveName = ""; QString strVolumeId = ""; QString strVolumeName = ""; QString strMountId = ""; QString strMountUri = ""; unsigned uFlag = 0; }EjectDeviceInfo; class MainWindow; class FDClickWidget : public QWidget { Q_OBJECT public: explicit FDClickWidget(QWidget *parent = nullptr, unsigned diskNo = 0, QString strDriveId = "", QString strVolumeId = "", QString strMountId = "", QString driveName = "", QString volumeName = "", quint64 capacityDis = 0, QString strMountUri = ""); ~FDClickWidget(); protected: void mousePressEvent(QMouseEvent *ev); void mouseReleaseEvent(QMouseEvent *ev); private: QIcon imgIcon; unsigned m_uDiskNo; QString m_driveName; QString m_volumeName; quint64 m_capacityDis; QString m_mountUri; QString m_driveId; QString m_volumeId; QString m_mountId; MainWindow *m_mainwindow; QPoint mousePos; QLabel *image_show_label; QLabel *m_driveName_label; ClickLabel *m_nameDis1_label; QLabel *m_capacityDis1_label; QWidget *disWidgetNumOne; QGSettings *fontSettings = nullptr; QGSettings *qtSettings = nullptr; int fontSize; QString currentThemeMode; QString m_strCapacityDis; public: QPushButton *m_eject_button = nullptr; interactiveDialog *chooseDialog = nullptr; gpartedInterface *gpartedface = nullptr; bool ifSucess = false; Q_SIGNALS: void clicked(); void clickedEject(EjectDeviceInfo eDeviceInfo); void noDeviceSig(); void themeFontChange(qreal lfFontSize); private Q_SLOTS: void on_volume_clicked(); void switchWidgetClicked(); void onThemeFontChange(qreal lfFontSize); private: QString size_human(qlonglong capacity); QPixmap drawSymbolicColoredPixmap(const QPixmap &source); protected: bool eventFilter(QObject *obj, QEvent *event); void resizeEvent(QResizeEvent *event); public: void initFontSize(); void initThemeMode(); }; #endif // __FDCLICKWIDGET_H__ ukui-panel-3.0.6.4/ukui-flash-disk/MainController.cpp0000644000175000017500000000252314203402514021005 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see //#include "stdlib.h" MainController* MainController::mSelf = 0; //static variable MainController* MainController::self() //static function //complete the singleton object { if (!mSelf) { mSelf = new MainController; } return mSelf; } MainController::MainController() { } MainController::~MainController() { } int MainController::init() //init select { m_DiskWindow = new MainWindow; //main process singleton object connect(this, &MainController::notifyWnd, m_DiskWindow, &MainWindow::onNotifyWnd); return 0; } ukui-panel-3.0.6.4/ukui-flash-disk/fdframe.h0000644000175000017500000000223114203402514017122 0ustar fengfeng/* * Copyright (C) 2021 KylinSoft Co., Ltd. * * Authors: * Yang Min yangmin@kylinos.cn * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include class FDFrame : public QFrame { Q_OBJECT public: explicit FDFrame(QWidget* parent); virtual ~FDFrame(); void initOpacityGSettings(); protected: void paintEvent(QPaintEvent * event); private: // QGSettings QGSettings *m_gsTransOpacity = nullptr; qreal m_curTransOpacity = 1; }; #endif ukui-panel-3.0.6.4/ukui-flash-disk/qclickwidget.h0000644000175000017500000001014014203402514020166 0ustar fengfeng/* * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program or library is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA */ #ifndef QCLICKWIDGET_H #define QCLICKWIDGET_H #include #include #include #include #include #include #include #include #include #include #include #include #include "ejectInterface.h" #include "clickLabel.h" #include "UnionVariable.h" #include "interactivedialog.h" #include "gpartedinterface.h" class MainWindow; class QClickWidget : public QWidget { Q_OBJECT public: explicit QClickWidget(QWidget *parent = nullptr, int num = 0, GDrive *Drive=NULL, GVolume *Volume=NULL, QString driveName=NULL, QString nameDis1=NULL, QString nameDis2 =NULL, QString nameDis3 = NULL, QString nameDis4 = NULL, qlonglong capacityDis1=0, qlonglong capacityDis2=0, qlonglong capacityDis3=0, qlonglong capacityDis4=0, QString pathDis1=NULL, QString pathDis2=NULL, QString pathDis3=NULL, QString pathDis4=NULL); ~QClickWidget(); public Q_SLOTS: void mouseClicked(); protected: void mousePressEvent(QMouseEvent *ev); void mouseReleaseEvent(QMouseEvent *ev); //void paintEvent(QPaintEvent *); private: QIcon imgIcon; QString m_driveName; QString m_nameDis1; QString m_nameDis2; QString m_nameDis3; QString m_nameDis4; qlonglong m_capacityDis1; qlonglong m_capacityDis2; qlonglong m_capacityDis3; qlonglong m_capacityDis4; QString m_pathDis1; QString m_pathDis2; QString m_pathDis3; QString m_pathDis4; MainWindow *m_mainwindow; QPoint mousePos; int m_Num; GDrive *m_Drive; QLabel *image_show_label; QLabel *m_driveName_label; ClickLabel *m_nameDis1_label; ClickLabel *m_nameDis2_label; ClickLabel *m_nameDis3_label; ClickLabel *m_nameDis4_label; QLabel *m_capacityDis1_label; QLabel *m_capacityDis2_label; QLabel *m_capacityDis3_label; QLabel *m_capacityDis4_label; QWidget *disWidgetNumOne; QWidget *disWidgetNumTwo; QWidget *disWidgetNumThree; QWidget *disWidgetNumFour; QGSettings *fontSettings = nullptr; QGSettings *qtSettings = nullptr; int fontSize; QString currentThemeMode; public: QPushButton *m_eject_button = nullptr; ejectInterface *m_eject = nullptr; interactiveDialog *chooseDialog = nullptr; gpartedInterface *gpartedface = nullptr; bool ifSucess; int flagType; Q_SIGNALS: void clicked(); void clickedConvert(); void noDeviceSig(); private Q_SLOTS: void on_volume1_clicked(); void on_volume2_clicked(); void on_volume3_clicked(); void on_volume4_clicked(); void switchWidgetClicked(); private: QString size_human(qlonglong capacity); QPixmap drawSymbolicColoredPixmap(const QPixmap &source); protected: bool eventFilter(QObject *obj, QEvent *event); void resizeEvent(QResizeEvent *event); public: void initFontSize(); void initThemeMode(); }; #endif ukui-panel-3.0.6.4/ukui-flash-disk/device-operation.cpp0000644000175000017500000002420014203402514021306 0ustar fengfeng/* * Copyright (C) 2021 KylinSoft Co., Ltd. * * Authors: * Ding Jing dingjing@kylinos.cn * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see static void formatCB (GObject* sourceObject, GAsyncResult* res, gpointer udata); static void repairCB (GObject* sourceObject, GAsyncResult* res, gpointer udata); DeviceOperation::DeviceOperation(GDrive *drive, QObject *parent) : QObject(parent) { g_return_if_fail(drive); g_autofree char* devName = g_drive_get_identifier(drive, G_DRIVE_IDENTIFIER_KIND_UNIX_DEVICE); g_return_if_fail(devName); g_autoptr(UDisksClient) client = udisks_client_new_sync(NULL, NULL); g_return_if_fail(client); g_autoptr(UDisksObject) udiskObj = getObjectFromBlockDevice(client, devName); g_return_if_fail(udiskObj); mDiskBlock = udisks_object_get_block(udiskObj); mDiskManager = udisks_object_get_manager(udiskObj); mDiskFilesystem = udisks_object_get_filesystem(udiskObj); } DeviceOperation::DeviceOperation(GVolume* volume, QObject *parent) : QObject(parent) { g_return_if_fail(volume); g_autofree char* devName = g_volume_get_identifier(volume, G_DRIVE_IDENTIFIER_KIND_UNIX_DEVICE); g_return_if_fail(devName); g_autoptr(UDisksClient) client = udisks_client_new_sync(NULL, NULL); g_return_if_fail(client); g_autoptr(UDisksObject) udiskObj = getObjectFromBlockDevice(client, devName); g_return_if_fail(udiskObj); mDiskBlock = udisks_object_get_block(udiskObj); mDiskManager = udisks_object_get_manager(udiskObj); mDiskFilesystem = udisks_object_get_filesystem(udiskObj); } DeviceOperation::~DeviceOperation() { g_clear_object(&mDiskBlock); g_clear_object(&mDiskManager); g_clear_object(&mDiskFilesystem); } bool DeviceOperation::repairFilesystem(GDrive *drive) { gboolean ret = FALSE; g_return_val_if_fail(drive, ret); g_autofree char* devName = g_drive_get_identifier (drive, G_DRIVE_IDENTIFIER_KIND_UNIX_DEVICE); g_return_val_if_fail(devName, ret); g_autoptr(UDisksClient) client = udisks_client_new_sync(NULL, NULL); g_return_val_if_fail(client, ret); g_autoptr (UDisksObject) udiskObj = getObjectFromBlockDevice(client, devName); g_return_val_if_fail(udiskObj, ret); g_autoptr (UDisksFilesystem) diskFilesystem = udisks_object_get_filesystem(udiskObj); GVariantBuilder optionsBuilder; g_variant_builder_init(&optionsBuilder, G_VARIANT_TYPE_VARDICT); udisks_filesystem_call_repair_sync(diskFilesystem, g_variant_builder_end(&optionsBuilder), &ret, nullptr, nullptr); return ret; } bool DeviceOperation::repairFilesystem(GVolume *volume) { gboolean ret = FALSE; g_return_val_if_fail(volume, ret); g_autofree char* devName = g_volume_get_identifier (volume, G_DRIVE_IDENTIFIER_KIND_UNIX_DEVICE); g_return_val_if_fail(devName, ret); g_autoptr(UDisksClient) client = udisks_client_new_sync(NULL, NULL); g_return_val_if_fail(client, ret); g_autoptr (UDisksObject) udiskObj = getObjectFromBlockDevice(client, devName); g_return_val_if_fail(udiskObj, ret); g_autoptr (UDisksFilesystem) diskFilesystem = udisks_object_get_filesystem(udiskObj); GVariantBuilder optionsBuilder; g_variant_builder_init(&optionsBuilder, G_VARIANT_TYPE_VARDICT); udisks_filesystem_call_repair_sync(diskFilesystem, g_variant_builder_end(&optionsBuilder), &ret, nullptr, nullptr); return ret; } gint64 DeviceOperation::getDriveSize(GDrive *drive) { gint64 ret = 0; g_return_val_if_fail(drive, ret); g_autofree char* devName = g_drive_get_identifier (drive, G_DRIVE_IDENTIFIER_KIND_UNIX_DEVICE); g_return_val_if_fail(devName, ret); g_autoptr(UDisksClient) client = udisks_client_new_sync(NULL, NULL); g_return_val_if_fail(client, ret); g_autoptr (UDisksObject) udiskObj = getObjectFromBlockDevice(client, devName); g_return_val_if_fail(udiskObj, ret); g_autoptr (UDisksBlock) diskBlock = udisks_object_get_block (udiskObj); return udisks_block_get_size(diskBlock); } gchar *DeviceOperation::getDriveLabel(GDrive *drive) { gchar* ret = NULL; g_return_val_if_fail(drive, ret); g_autofree char* devName = g_drive_get_identifier (drive, G_DRIVE_IDENTIFIER_KIND_UNIX_DEVICE); g_return_val_if_fail(devName, ret); ret = g_strdup (devName); g_autoptr(UDisksClient) client = udisks_client_new_sync(NULL, NULL); g_return_val_if_fail(client, ret); g_autoptr (UDisksObject) udiskObj = getObjectFromBlockDevice(client, devName); g_return_val_if_fail(udiskObj, ret); g_autoptr (UDisksBlock) diskBlock = udisks_object_get_block (udiskObj); g_return_val_if_fail(udiskObj, ret); // cannot free const gchar* label = udisks_block_get_id_label (diskBlock); if (label && 0 != g_strcmp0 (label, "") && 0 != g_strcmp0 (label, " ")) { if (ret) g_free(ret); ret = g_strdup (label);}; return ret; } gchar *DeviceOperation::getDriveLabel(GVolume *volume) { gchar* ret = NULL; g_return_val_if_fail(volume, ret); g_autofree char* devName = g_volume_get_identifier (volume, G_DRIVE_IDENTIFIER_KIND_UNIX_DEVICE); g_return_val_if_fail(devName, ret); ret = g_strdup (devName); g_autoptr(UDisksClient) client = udisks_client_new_sync(NULL, NULL); g_return_val_if_fail(client, ret); g_autoptr (UDisksObject) udiskObj = getObjectFromBlockDevice(client, devName); g_return_val_if_fail(udiskObj, ret); g_autoptr (UDisksBlock) diskBlock = udisks_object_get_block (udiskObj); g_return_val_if_fail(udiskObj, ret); // cannot free const gchar* label = udisks_block_get_id_label (diskBlock); if (label && 0 != g_strcmp0 (label, "") && 0 != g_strcmp0 (label, " ")) { if (ret) g_free(ret); ret = g_strdup (label);}; return ret; } void DeviceOperation::udiskFormat(QString type, QString labelName) { if (!mDiskBlock) { Q_EMIT formatFinished(false); return; } GVariantBuilder optionsBuilder; g_variant_builder_init(&optionsBuilder, G_VARIANT_TYPE_VARDICT); g_variant_builder_add (&optionsBuilder, "{sv}", "label", g_variant_new_string (labelName.toUtf8().constData())); g_variant_builder_add (&optionsBuilder, "{sv}", "take-ownership", g_variant_new_boolean (TRUE)); g_variant_builder_add (&optionsBuilder, "{sv}", "update-partition-type", g_variant_new_boolean (TRUE)); // g_cancellable_reset(&mFormatCancel); udisks_block_call_format(mDiskBlock, type.toLower().toUtf8().constData(), g_variant_builder_end(&optionsBuilder), nullptr /*&mFormatCancel*/, GAsyncReadyCallback(formatCB), this); } void DeviceOperation::udiskRepair() { if (!mDiskFilesystem) { Q_EMIT repairFinished(false); return; } GVariantBuilder optionsBuilder; g_variant_builder_init(&optionsBuilder, G_VARIANT_TYPE_VARDICT); // g_cancellable_reset(&mRepairCancel); udisks_filesystem_call_repair(mDiskFilesystem, g_variant_builder_end(&optionsBuilder), nullptr /*&mRepairCancel*/, GAsyncReadyCallback(repairCB), this); } void DeviceOperation::udiskFormatCancel() { // if (g_cancellable_is_cancelled(&mFormatCancel)) { // g_cancellable_cancel(&mFormatCancel); // } } void DeviceOperation::udiskRepairCancel() { // if (g_cancellable_is_cancelled(&mRepairCancel)) { // g_cancellable_cancel(&mRepairCancel); // } } QString DeviceOperation::udiskSize() { g_return_val_if_fail(mDiskBlock, tr("unknown")); guint64 size = udisks_block_get_size(mDiskBlock); g_autofree char* str = g_format_size_full(size, G_FORMAT_SIZE_IEC_UNITS); return str; } QString DeviceOperation::udiskUUID() { g_return_val_if_fail(mDiskBlock, tr("unknown")); const char* str = udisks_block_get_id_uuid(mDiskBlock); return str; } QString DeviceOperation::udiskLabel() { g_return_val_if_fail(mDiskBlock, tr("unknown")); const char* str = udisks_block_get_id_label(mDiskBlock); return str; } UDisksObject* DeviceOperation::getObjectFromBlockDevice(UDisksClient* client, const gchar* bdevice) { struct stat statbuf; UDisksObject* object = NULL; UDisksObject* cryptoBackingObject = NULL; g_autofree const gchar* cryptoBackingDevice = NULL; g_return_val_if_fail(stat(bdevice, &statbuf) == 0, object); // cannot free UDisksBlock* block = udisks_client_get_block_for_dev (client, statbuf.st_rdev); g_return_val_if_fail(block != NULL, object); object = UDISKS_OBJECT (g_dbus_interface_dup_object (G_DBUS_INTERFACE (block))); cryptoBackingDevice = udisks_block_get_crypto_backing_device ((udisks_object_peek_block (object))); cryptoBackingObject = udisks_client_get_object (client, cryptoBackingDevice); if (cryptoBackingObject != NULL) { g_object_unref (object); object = cryptoBackingObject; } return object; } static void formatCB (GObject* sourceObject, GAsyncResult* res, gpointer udata) { bool ret = true; GError* error = NULL; DeviceOperation* pThis = static_cast(udata); if (!udisks_block_call_format_finish (UDISKS_BLOCK(sourceObject), res, &error)) { if (NULL != error && NULL != strstr(error->message, "wipefs:")) { g_clear_error(&error); } ret = false; } Q_EMIT pThis->formatFinished(ret); } static void repairCB (GObject* sourceObject, GAsyncResult* res, gpointer udata) { GError* error = NULL; gboolean outRet = FALSE; DeviceOperation* pThis = static_cast(udata); if (!udisks_filesystem_call_repair_finish(UDISKS_FILESYSTEM(sourceObject), &outRet, res, &error)) { g_clear_error(&error); } Q_EMIT pThis->repairFinished(outRet); } ukui-panel-3.0.6.4/ukui-flash-disk/mainwindow.ui0000644000175000017500000000074614203402514020071 0ustar fengfeng MainWindow 0 0 370 232 MainWindow ukui-panel-3.0.6.4/ukui-flash-disk/main.cpp0000644000175000017500000000551714203402514017007 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include #include #include #include #include #include #include #include "UnionVariable.h" #include "mainwindow.h" #include "MainController.h" #include "fdapplication.h" int main(int argc, char *argv[]) { initUkuiLog4qt("ukui-flash-disk"); QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); #if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)) QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough); #endif QTextCodec *codec = QTextCodec::codecForName("utf8"); //Linux QTextCodec::setCodecForLocale(codec); QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QString id = QString("ukui-flash-disk_%1_%2").arg(getuid()).arg(QLatin1String(getenv("DISPLAY"))); FDApplication a(id, argc, argv); // Process does not exit implicitly a.setQuitOnLastWindowClosed(false); if (a.isRunning()) { qInfo() << "ukui-flash-disk is running, now exit!"; return 1; } // load translation file QString locale = QLocale::system().name(); QTranslator translator; if (locale == "zh_CN") { if (translator.load("/usr/share/ukui/ukui-panel/ukui-flash-disk_zh_CN.qm")) { qDebug() << "load success"; a.installTranslator(&translator); } else { qDebug() << "Load translations file" << locale << "failed!"; } } if (QApplication::desktop()->width() >= 2560) { #if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)) QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); #endif } MainController *ctrl = MainController::self(); // single instance is running if (ctrl->init() != 0) { return 0; } QObject::connect(&a, &FDApplication::notifyWnd, ctrl, &MainController::notifyWnd); a.exec(); delete ctrl; return 0; } ukui-panel-3.0.6.4/ukui-flash-disk/interactivedialog.cpp0000644000175000017500000002103514203402514021551 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see interactiveDialog::interactiveDialog(QString strDevId, QWidget *parent):QWidget(parent) { this->setFixedSize(300,86); this->setWindowFlags(Qt::FramelessWindowHint | Qt::Popup); m_strDevId = strDevId; QPainterPath path; auto rect = this->rect(); rect.adjust(1, 1, -1, -1); path.addRoundedRect(rect, 6, 6); setProperty("blurRegion", QRegion(path.toFillPolygon().toPolygon())); this->setAttribute(Qt::WA_TranslucentBackground); initWidgets(); connect(chooseBtnCancle,SIGNAL(clicked()),this,SLOT(close())); connect(chooseBtnContinue,SIGNAL(clicked()),this,SLOT(convert())); moveChooseDialogRight(); initTransparentState(); getTransparentData(); KWindowEffects::enableBlurBehind(this->winId(), true, QRegion(path.toFillPolygon().toPolygon())); } void interactiveDialog::initTransparentState() { const QByteArray idtrans(THEME_QT_TRANS); if(QGSettings::isSchemaInstalled(idtrans)) { m_transparency_gsettings = new QGSettings(idtrans); } } void interactiveDialog::getTransparentData() { if (!m_transparency_gsettings) { m_transparency = 0.95; return; } QStringList keys = m_transparency_gsettings->keys(); if (keys.contains("transparency")) { m_transparency = m_transparency_gsettings->get("transparency").toDouble(); } } void interactiveDialog::initWidgets() { contentLable = new QLabel(this); contentLable->setWordWrap(true); #ifdef UDISK_SUPPORT_FORCEEJECT if (m_strDevId.startsWith("/dev/sr")) { contentLable->setText(tr("cdrom is occupying,do you want to eject it")); } else if (m_strDevId.startsWith("/dev/mmcblk")) { contentLable->setText(tr("sd is occupying,do you want to eject it")); } else { contentLable->setText(tr("usb is occupying,do you want to eject it")); } #else if (m_strDevId.startsWith("/dev/sr")) { contentLable->setText(tr("cdrom is occupying")); } else if (m_strDevId.startsWith("/dev/mmcblk")) { contentLable->setText(tr("sd is occupying")); } else { contentLable->setText(tr("usb is occupying")); } #endif content_H_BoxLayout = new QHBoxLayout(); content_H_BoxLayout->addWidget(contentLable, 1, Qt::AlignCenter); #ifdef UDISK_SUPPORT_FORCEEJECT chooseBtnCancle = new QPushButton(); chooseBtnCancle->setText(tr("cancle")); chooseBtnCancle->setFlat(true); chooseBtnContinue = new QPushButton(); chooseBtnContinue->setText(tr("yes")); chooseBtnContinue->setFlat(true); chooseBtn_H_BoxLayout = new QHBoxLayout(); chooseBtn_H_BoxLayout->addSpacing(70); chooseBtn_H_BoxLayout->addWidget(chooseBtnCancle); chooseBtn_H_BoxLayout->addWidget(chooseBtnContinue); chooseBtn_H_BoxLayout->setSpacing(0); #else chooseBtnCancle = new QPushButton(); chooseBtnCancle->setText(tr("yes")); chooseBtnCancle->setFlat(true); chooseBtnContinue = new QPushButton(); chooseBtnContinue->hide(); chooseBtn_H_BoxLayout = new QHBoxLayout(); chooseBtn_H_BoxLayout->addWidget(chooseBtnCancle, 1, Qt::AlignCenter); chooseBtn_H_BoxLayout->addWidget(chooseBtnContinue); chooseBtn_H_BoxLayout->setSpacing(0); #endif main_V_BoxLayout = new QVBoxLayout(); main_V_BoxLayout->addLayout(content_H_BoxLayout); main_V_BoxLayout->addLayout(chooseBtn_H_BoxLayout); this->setLayout(main_V_BoxLayout); } void interactiveDialog::convert() { Q_EMIT FORCESIG(); } void interactiveDialog::moveChooseDialogRight() { int position=0; int panelSize=0; if(QGSettings::isSchemaInstalled(QString("org.ukui.panel.settings").toLocal8Bit())) { QGSettings* gsetting=new QGSettings(QString("org.ukui.panel.settings").toLocal8Bit()); if(gsetting->keys().contains(QString("panelposition"))) position=gsetting->get("panelposition").toInt(); else position=0; if(gsetting->keys().contains(QString("panelsize"))) panelSize=gsetting->get("panelsize").toInt(); else panelSize=SmallPanelSize; } else { position=0; panelSize=SmallPanelSize; } int x=QApplication::primaryScreen()->geometry().x(); int y=QApplication::primaryScreen()->geometry().y(); qDebug()<<"QApplication::primaryScreen()->geometry().x();"<geometry().x(); qDebug()<<"QApplication::primaryScreen()->geometry().y();"<geometry().y(); if(position==0) this->setGeometry(QRect(x + QApplication::primaryScreen()->geometry().width()-this->width() - DISTANCEPADDING - DISTANCEMEND,y+QApplication::primaryScreen()->geometry().height()-panelSize-this->height() - DISTANCEPADDING,this->width(),this->height())); else if(position==1) this->setGeometry(QRect(x + QApplication::primaryScreen()->geometry().width()-this->width() - DISTANCEPADDING - DISTANCEMEND,y+panelSize + DISTANCEPADDING,this->width(),this->height())); // Style::minw,Style::minh the width and the height of the interface which you want to show else if(position==2) this->setGeometry(QRect(x+panelSize + DISTANCEPADDING,y + QApplication::primaryScreen()->geometry().height() - this->height() - DISTANCEPADDING,this->width(),this->height())); else this->setGeometry(QRect(x+QApplication::primaryScreen()->geometry().width()-panelSize-this->width() - DISTANCEPADDING,y + QApplication::primaryScreen()->geometry().height() - this->height() - DISTANCEPADDING,this->width(),this->height())); } interactiveDialog::~interactiveDialog() { if (m_transparency_gsettings) { delete m_transparency_gsettings; m_transparency_gsettings = nullptr; } if (gsetting) { delete gsetting; gsetting = nullptr; } } void interactiveDialog::paintEvent(QPaintEvent *event) { // QStyleOption opt; // opt.init(this); // QPainter p(this); // QRect rect = this->rect(); // p.setRenderHint(QPainter::Antialiasing); // 反锯齿; // p.setBrush(opt.palette.color(QPalette::Base)); //// p.setBrush(QColor(Qt::red)); //// p.setOpacity(m_transparency); // p.setPen(Qt::NoPen); // p.drawRoundedRect(rect, 6, 6); // qDebug()<<__FUNCTION__; // QStyleOption opt; // opt.init(this); // QPainter p(this); // QRect rect = this->rect(); // p.setRenderHint(QPainter::Antialiasing); // 反锯齿; // p.setBrush(opt.palette.color(QPalette::Base)); // p.setOpacity(m_transparency); // p.setPen(Qt::NoPen); // p.drawRoundedRect(rect, 6, 6); // QWidget::paintEvent(event); // qDebug()<<__FUNCTION__; // QStyleOption opt; // opt.init(this); // QPainter p(this); // QRect rect = this->rect(); // p.setRenderHint(QPainter::Antialiasing); // 反锯齿; // p.setBrush(opt.palette.color(QPalette::Base)); // p.setOpacity(m_transparency); // p.setPen(Qt::NoPen); // p.drawRect(rect); // QWidget::paintEvent(event); // QStyleOption opt; // opt.init(this); // QPainter p(this); // p.setRenderHint(QPainter::Antialiasing); // 反锯齿; // p.setBrush(opt.palette.color(QPalette::Base)); // p.setOpacity(m_transparency); // QPainterPath path; // auto rect = this->rect(); // path.addRoundedRect(rect, 12, 12); // path.drawRoundedRect // QRegion region(path.toFillPolygon().toPolygon()); //// this->setAttribute(Qt::WA_TranslucentBackground);//设置窗口背景透明 // KWindowEffects::enableBlurBehind(this->winId(),true,region); // QWidget::paintEvent(event); QStyleOption opt; opt.init(this); QPainter p(this); QRect rect = this->rect(); p.setRenderHint(QPainter::Antialiasing); // 反锯齿; p.setBrush(opt.palette.color(QPalette::Base)); p.setOpacity(m_transparency); p.setPen(Qt::NoPen); p.drawRoundedRect(rect, 6, 6); QWidget::paintEvent(event); } ukui-panel-3.0.6.4/plugin-startmenu/0000755000175000017500000000000014204636772015705 5ustar fengfengukui-panel-3.0.6.4/plugin-startmenu/startmenu.h0000644000175000017500000000547214204636772020110 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include #include #include #include #include #include //#include "../panel/plugin.h" #include "../panel/ukuipanel.h" //#include "../panel/config/configpanelwidget.h" //#include <../panel/popupmenu.h> #include #include #include "../panel/highlight-effect.h" class UKUIStartMenuButton; class UKUIStartMenuPlugin: public QObject, public IUKUIPanelPlugin { Q_OBJECT public: explicit UKUIStartMenuPlugin(const IUKUIPanelPluginStartupInfo &startupInfo); ~UKUIStartMenuPlugin(); virtual QWidget *widget(); virtual QString themeId() const { return "StartMenu"; } virtual Flags flags() const { return NeedsHandle; } void realign(); bool isSeparate() const { return true; } private: UKUIStartMenuButton *mWidget; }; class StartMenuLibrary: public QObject, public IUKUIPanelPluginLibrary { Q_OBJECT Q_PLUGIN_METADATA(IID "ukui.org/Panel/PluginInterface/3.0") Q_INTERFACES(IUKUIPanelPluginLibrary) public: IUKUIPanelPlugin *mPlugin; IUKUIPanelPlugin *instance(const IUKUIPanelPluginStartupInfo &startupInfo) const { return new UKUIStartMenuPlugin(startupInfo); } }; class UKUIStartMenuButton:public QToolButton { Q_OBJECT public: UKUIStartMenuButton(IUKUIPanelPlugin *plugin, QWidget* parent = 0); ~UKUIStartMenuButton(); void realign(); protected: void contextMenuEvent(QContextMenuEvent *event); void mousePressEvent(QMouseEvent* event); void enterEvent(QEvent *); void leaveEvent(QEvent *); private: QMenu *rightPressMenu; IUKUIPanelPlugin * mPlugin; QString version; void getOsRelease(); QString getCanHibernateResult(); private slots: void ScreenServer(); void SessionSwitch(); void SessionLogout(); void SessionReboot(); void TimeShutdown(); void SessionShutdown(); void SessionSuspend(); void SessionHibernate(); }; #endif ukui-panel-3.0.6.4/plugin-startmenu/startmenu.cpp0000644000175000017500000002170414204636772020437 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include #include #include #include "QDebug" #include "QByteArray" #include "QFileInfo" #include "../panel/customstyle.h" UKUIStartMenuPlugin::UKUIStartMenuPlugin(const IUKUIPanelPluginStartupInfo &startupInfo): QObject(), IUKUIPanelPlugin(startupInfo), mWidget(new UKUIStartMenuButton(this)) { } UKUIStartMenuPlugin::~UKUIStartMenuPlugin() { delete mWidget; } QWidget *UKUIStartMenuPlugin::widget() { return mWidget; } void UKUIStartMenuPlugin::realign() { mWidget->realign(); } UKUIStartMenuButton::UKUIStartMenuButton( IUKUIPanelPlugin *plugin, QWidget* parent ): QToolButton(parent), mPlugin(plugin) { qDebug()<<"Plugin-StartMenu :: UKUIStartMenuButton start"; this->setIcon(QIcon("/usr/share/ukui-panel/panel/img/startmenu.svg")); this->setStyle(new CustomStyle()); setStyleSheet("QToolButton { margin-left: 4px; } "); QTimer::singleShot(5000,[this] {this->setToolTip(tr("UKui Menu")); }); // this->setWindowFlags(Qt::NoFocus); //setAttribute(Qt::WA_X11DoNotAcceptFocus, true); //setAttribute(Qt::WA_ShowWithoutActivating,true); //setFocusPolicy(Qt::NoFocus); qDebug()<<"Plugin-StartMenu :: UKUIStartMenuButton end"; } UKUIStartMenuButton::~UKUIStartMenuButton() { } /*plugin-startmenu refresh function*/ void UKUIStartMenuButton::realign() { if (mPlugin->panel()->isHorizontal()) this->setFixedSize(mPlugin->panel()->panelSize()*1.3,mPlugin->panel()->panelSize()); else this->setFixedSize(mPlugin->panel()->panelSize(),mPlugin->panel()->panelSize()*1.3); this->setIconSize(QSize(mPlugin->panel()->iconSize(),mPlugin->panel()->iconSize())); } void UKUIStartMenuButton::mousePressEvent(QMouseEvent* event) { const Qt::MouseButton b = event->button(); if (Qt::LeftButton == b) { if(QFileInfo::exists(QString("/usr/bin/ukui-menu"))) { QProcess *process =new QProcess(this); process->startDetached("/usr/bin/ukui-menu"); process->deleteLater(); } else{qDebug()<<"not find /usr/bin/ukui-start-menu"<setAttribute(Qt::WA_DeleteOnClose); QMenu *pUserAction=new QMenu(tr("User Action")); //用户操作 QMenu *pSleepHibernate=new QMenu(tr("Sleep or Hibernate")); //重启或休眠 QMenu *pPowerSupply=new QMenu(tr("Power Supply")); //电源 rightPressMenu->addMenu(pUserAction); rightPressMenu->addMenu(pSleepHibernate); rightPressMenu->addMenu(pPowerSupply); pUserAction->addAction(QIcon::fromTheme("system-lock-screen-symbolic"), tr("Lock Screen"), this, SLOT(ScreenServer()) ); //锁屏 pUserAction->addAction(QIcon::fromTheme("stock-people-symbolic"), tr("Switch User"), this, SLOT(SessionSwitch()) ); //切换用户 pUserAction->addAction(QIcon::fromTheme("system-logout-symbolic"), tr("Logout"), this, SLOT(SessionLogout()) ); //注销 /* //社区版本 安装时未强求建立 swap分区,若未建swap分区,会导致休眠(hibernate)失败,所以在20.04上屏蔽该功能 getOsRelease(); if(QString::compare(version,"Ubuntu")) 或使用!QString::compare(getCanHibernateResult(),"yes") 【目前该接口有bug】 */ //检测CanHibernate接口的返回值,判断是否可以执行挂起操作 QString filename = QDir::homePath() + "/.config/ukui/panel-commission.ini"; QSettings m_settings(filename, QSettings::IniFormat); m_settings.setIniCodec("UTF-8"); m_settings.beginGroup("Hibernate"); QString hibernate_action = m_settings.value("hibernate", "").toString(); if (hibernate_action.isEmpty()) { hibernate_action = "show"; } m_settings.endGroup(); if(QString::compare(version,"Ubuntu") && hibernate_action != "hide"){ pSleepHibernate->addAction(QIcon::fromTheme("kylin-sleep-symbolic"), tr("Hibernate Mode"), this, SLOT(SessionHibernate()) ); //休眠 } pSleepHibernate->addAction(QIcon::fromTheme("system-sleep"), tr("Sleep Mode"), this, SLOT(SessionSuspend()) ); //睡眠 pPowerSupply->addAction(QIcon::fromTheme("system-restart-symbolic"), tr("Restart"), this, SLOT(SessionReboot()) ); //重启 QFileInfo file("/usr/bin/time-shutdown"); if(file.exists()) pPowerSupply->addAction(QIcon::fromTheme("ukui-shutdown-timer-symbolic"), tr("TimeShutdown"), this, SLOT(TimeShutdown()) ); //定时开关机 pPowerSupply->addAction(QIcon::fromTheme("system-shutdown-symbolic"), tr("Power Off"), this, SLOT(SessionShutdown()) ); //关机 rightPressMenu->setGeometry(mPlugin->panel()->calculatePopupWindowPos(mapToGlobal(event->pos()), rightPressMenu->sizeHint())); rightPressMenu->show(); } /*开始菜单按钮右键菜单选项,与开始菜单中电源按钮的右键功能是相同的*/ //锁屏 void UKUIStartMenuButton::ScreenServer() { system("ukui-screensaver-command -l"); } //切换用户 void UKUIStartMenuButton::SessionSwitch() { QProcess::startDetached(QString("ukui-session-tools --switchuser")); } //注销 void UKUIStartMenuButton::SessionLogout() { system("ukui-session-tools --logout"); } //休眠 睡眠 void UKUIStartMenuButton::SessionHibernate() { system("ukui-session-tools --hibernate"); } //睡眠 void UKUIStartMenuButton::SessionSuspend() { system("ukui-session-tools --suspend"); } //重启 void UKUIStartMenuButton::SessionReboot() { system("ukui-session-tools --reboot"); } //定时关机 void UKUIStartMenuButton::TimeShutdown() { QProcess *process_timeshutdowm =new QProcess(this); process_timeshutdowm->startDetached("/usr/bin/time-shutdown"); process_timeshutdowm->deleteLater(); } //关机 void UKUIStartMenuButton::SessionShutdown() { system("ukui-session-tools --shutdown"); } //获取系统版本,若为ubuntu则取消休眠功能 void UKUIStartMenuButton::getOsRelease() { QFile file("/etc/lsb-release"); if (!file.open(QIODevice::ReadOnly)) qDebug() << "Read file Failed."; while (!file.atEnd()) { QByteArray line = file.readLine(); QString str(line); if (str.contains("DISTRIB_ID")){ version=str.remove("DISTRIB_ID="); version=str.remove("\n"); } } } //检测当前系统能否执行休眠操作 QString UKUIStartMenuButton::getCanHibernateResult() { QDBusInterface interface("org.freedesktop.login1", "/org/freedesktop/login1", "org.freedesktop.login1.Manager", QDBusConnection::systemBus()); if (!interface.isValid()) { qCritical() << QDBusConnection::sessionBus().lastError().message(); } /*调用远程的 CanHibernate 方法,判断是否可以执行休眠的操作,返回值为yes为允许执行休眠,no为无法执行休眠 na为交换分区不足*/ QDBusReply reply = interface.call("CanHibernate"); if (reply.isValid()) { return reply; } else { qCritical() << "Call Dbus method failed"; } } void UKUIStartMenuButton::enterEvent(QEvent *) { repaint(); return; } void UKUIStartMenuButton::leaveEvent(QEvent *) { repaint(); return; } ukui-panel-3.0.6.4/plugin-startmenu/img/0000755000175000017500000000000014204636772016461 5ustar fengfengukui-panel-3.0.6.4/plugin-startmenu/img/startmenu.svg0000644000175000017500000001347014204636772021231 0ustar fengfeng ukui-panel-3.0.6.4/plugin-startmenu/resources/0000755000175000017500000000000014204636772017717 5ustar fengfengukui-panel-3.0.6.4/plugin-startmenu/resources/startmenu.desktop.in0000644000175000017500000000023414204636772023740 0ustar fengfeng[Desktop Entry] Type=Service ServiceTypes=UKUIPanel/Plugin Name=Start Menu Comment=Get the start menu under the cursor. For web developers. Icon=start-menu ukui-panel-3.0.6.4/plugin-startmenu/CMakeLists.txt0000644000175000017500000000041114204636772020441 0ustar fengfengset(PLUGIN "startmenu") set(HEADERS startmenu.h ) set(SOURCES startmenu.cpp ) set(UIS ) set(LIBRARIES ) install(FILES img/startmenu.svg DESTINATION "${PACKAGE_DATA_DIR}/plugin-startmenu/img" COMPONENT Runtime ) BUILD_UKUI_PLUGIN(${PLUGIN}) ukui-panel-3.0.6.4/README.md0000644000175000017500000000132214203402514013624 0ustar fengfeng# ukui-panel ukui-panel represents the taskbar of UKUI ## Table of Contents * [About Project](#About-Project) * [Getting Started](#Getting-Started) * [Document Introduction](#Document-Introduction) ## About Project ukui-panel contains the following plugins: * startmenu * quicklaunch * taskbar * tray * calendar * nightmode * showdesktop ... ## Getting Started ```bash # Install ukui-panel apt install ukui-panel # build from source and test mkdir build & cd build cmake .. make sudo make install ./panel/ukui-panel ``` ## Document Introduction ukui-panel has plugins configuration file in ~/.config/ukui/panel.conf it decide the count and order of the ukui-panel's plugins ukui-panel-3.0.6.4/CHANGELOG0000644000175000017500000000005614203402514013562 0ustar fengfengUse 'git log' for a detailed list of changes. ukui-panel-3.0.6.4/cmake/0000755000175000017500000000000014203402514013427 5ustar fengfengukui-panel-3.0.6.4/cmake/BuildPlugin.cmake0000644000175000017500000000761314203402514016656 0ustar fengfeng# - Try to find the UDev library # Once done this will define # # UDEV_FOUND - system has UDev # UDEV_INCLUDE_DIR - the libudev include directory # UDEV_LIBS - The libudev libraries # Copyright (c) 2010, Rafael Fernández López, # Copyright (c) 2016, Luís Pereira, # Copyright (c) 2019 Tianjin KYLIN Information Technology Co., Ltd. * # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # 3. Neither the name of the University nor the names of its contributors # may be used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. MACRO (BUILD_UKUI_PLUGIN NAME) set(PROGRAM "ukui-panel") project(${PROGRAM}_${NAME}) set(PROG_SHARE_DIR ${CMAKE_INSTALL_FULL_DATAROOTDIR}/ukui/${PROGRAM}) set(PLUGIN_SHARE_DIR ${PROG_SHARE_DIR}/${NAME}) # Translations ********************************** # ukui_translate_ts(${PROJECT_NAME}_QM_FILES # UPDATE_TRANSLATIONS ${UPDATE_TRANSLATIONS} # SOURCES # ${HEADERS} # ${SOURCES} # ${MOCS} # ${UIS} # TEMPLATE # ${NAME} # INSTALL_DIR # ${UKUI_TRANSLATIONS_DIR}/${PROGRAM}/${NAME} # ) file (GLOB ${PROJECT_NAME}_DESKTOP_FILES_IN resources/*.desktop.in) ukui_translate_desktop(DESKTOP_FILES SOURCES ${${PROJECT_NAME}_DESKTOP_FILES_IN} ) ukui_plugin_translation_loader(QM_LOADER ${NAME} "ukui-panel") #************************************************ file (GLOB CONFIG_FILES resources/*.conf) if (NOT DEFINED PLUGIN_DIR) set (PLUGIN_DIR ${CMAKE_INSTALL_FULL_LIBDIR}/${PROGRAM}) endif (NOT DEFINED PLUGIN_DIR) set(QTX_LIBRARIES Qt5::Widgets) if(QT_USE_QTXML) set(QTX_LIBRARIES ${QTX_LIBRARIES} Qt5::Xml) endif() if(QT_USE_QTDBUS) set(QTX_LIBRARIES ${QTX_LIBRARIES} Qt5::DBus) endif() list(FIND STATIC_PLUGINS ${NAME} IS_STATIC) set(SRC ${HEADERS} ${SOURCES} ${QM_LOADER} ${MOC_SOURCES} ${${PROJECT_NAME}_QM_FILES} ${RESOURCES} ${UIS} ${DESKTOP_FILES}) if (${IS_STATIC} EQUAL -1) # not static add_library(${NAME} MODULE ${SRC}) # build dynamically loadable modules install(TARGETS ${NAME} DESTINATION ${PLUGIN_DIR}) # install the *.so file else() # static add_library(${NAME} STATIC ${SRC}) # build statically linked lib endif() #target_link_libraries(${NAME} ${QTX_LIBRARIES} ${LIBRARIES} KF5::WindowSystem) target_link_libraries(${NAME} ${QTX_LIBRARIES} ${LIBRARIES} KF5::WindowSystem) install(FILES ${CONFIG_FILES} DESTINATION ${PLUGIN_SHARE_DIR}) install(FILES ${DESKTOP_FILES} DESTINATION ${PROG_SHARE_DIR}) ENDMACRO(BUILD_UKUI_PLUGIN) ukui-panel-3.0.6.4/cmake/ukui-build-tools/0000755000175000017500000000000014203402514016637 5ustar fengfengukui-panel-3.0.6.4/cmake/ukui-build-tools/ukui-build-tools-config.cmake0000644000175000017500000000564014203402514024321 0ustar fengfeng# UDEV_FOUND - system has UDev # UDEV_INCLUDE_DIR - the libudev include directory # UDEV_LIBS - The libudev libraries # Copyright (c) 2010, Rafael Fernández López, # Copyright (c) 2016, Luís Pereira, # Copyright (c) 2019 Tianjin KYLIN Information Technology Co., Ltd. * # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # 3. Neither the name of the University nor the names of its contributors # may be used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. ####### Expanded from @PACKAGE_INIT@ by configure_package_config_file() ####### ####### Any changes to this file will be overwritten by the next CMake run #### ####### The input file was ukui-build-tools-config.cmake.in ######## get_filename_component(PACKAGE_PREFIX_DIR "${CMAKE_CURRENT_LIST_DIR}/../../../" ABSOLUTE) macro(set_and_check _var _file) set(${_var} "${_file}") if(NOT EXISTS "${_file}") message(FATAL_ERROR "File or directory ${_file} referenced by variable ${_var} does not exist !") endif() endmacro() macro(check_required_components _NAME) foreach(comp ${${_NAME}_FIND_COMPONENTS}) if(NOT ${_NAME}_${comp}_FOUND) if(${_NAME}_FIND_REQUIRED_${comp}) set(${_NAME}_FOUND FALSE) endif() endif() endforeach() endmacro() #################################################################################### set(UKUI_CMAKE_MODULES_DIR "${PACKAGE_PREFIX_DIR}/share/cmake/ukui-build-tools/modules/") set(UKUI_CMAKE_FIND_MODULES_DIR "${PACKAGE_PREFIX_DIR}/share/cmake/ukui-build-tools/find-modules/") list(APPEND CMAKE_MODULE_PATH "${UKUI_CMAKE_MODULES_DIR}" "${UKUI_CMAKE_FIND_MODULES_DIR}" ) ukui-panel-3.0.6.4/cmake/ukui-build-tools/ukui-build-tools-config-version.cmake0000644000175000017500000000402714203402514026002 0ustar fengfeng# UDEV_FOUND - system has UDev # UDEV_INCLUDE_DIR - the libudev include directory # UDEV_LIBS - The libudev libraries # Copyright (c) 2010, Rafael Fernández López, # Copyright (c) 2016, Luís Pereira, # Copyright (c) 2019 Tianjin KYLIN Information Technology Co., Ltd. * # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # 3. Neither the name of the University nor the names of its contributors # may be used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. set(PACKAGE_VERSION "0.6.0") if(PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION) set(PACKAGE_VERSION_COMPATIBLE FALSE) else() set(PACKAGE_VERSION_COMPATIBLE TRUE) if(PACKAGE_FIND_VERSION STREQUAL PACKAGE_VERSION) set(PACKAGE_VERSION_EXACT TRUE) endif() endif() ukui-panel-3.0.6.4/cmake/ukui-build-tools/modules/0000755000175000017500000000000014203402514020307 5ustar fengfengukui-panel-3.0.6.4/cmake/ukui-build-tools/modules/UKUiPluginTranslationLoader.cpp.in0000644000175000017500000000175214203402514026767 0ustar fengfeng/* This file has been generated by the CMake ukui_plugin_translation_loader(). * It loads UKUi plugin translations. * * Attention: All changes will be overwritten!!! */ #include #include #include "../panel/common/ukuitranslator.h" /* Dummy helper symbol for referencing. * In case plugin is linked as static (lib*.a) unreferenced objects are stripped in linking time * => we need to reference some symbol from this file to be not stripped as a whole. */ void * loadPluginTranslation_@catalog_name@_helper = nullptr; static void loadPluginTranslation() { //XXX: we don't use the QStringLiteral here because it causes SEGFAULT in static finalization time // (the string is stored in static QHash and it's destructor can reference already deleted static QString (generated by QStringLiteral)) UKUi::Translator::translatePlugin(QLatin1String("@catalog_name@"), QLatin1String("@plugin_type@")); } Q_COREAPP_STARTUP_FUNCTION(loadPluginTranslation) ukui-panel-3.0.6.4/cmake/ukui-build-tools/modules/UKUiTranslationLoader.cmake0000644000175000017500000000763414203402514025506 0ustar fengfeng#============================================================================= # Copyright 2014 Luís Pereira # Copyright 2019 Tianjin KYLIN Information Technology Co., Ltd. * # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # 1. Redistributions of source code must retain the copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # 3. The name of the author may not be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #============================================================================= # # These functions enables "automatic" translation loading in UKUi Qt5 apps # and libs. They generate a .cpp file that takes care of everything. The # user doesn't have to do anything in the source code. # # Typical use: # include(UKUiTranslationLoader) # ukui_app_translation_loader(ukui-app_QM_LOADER ${PROJECT_NAME}) # add_executable(${PROJECT_NAME} # ${ukui-app_QM_LOADER} # ... # ) # ukui_app_translation_loader( ) # The generated .cpp file is added to # Translations catalog to be loaded function(ukui_app_translation_loader source_files catalog_name) configure_file( #${UKUI_CMAKE_MODULES_DIR}/UKUiAppTranslationLoader.cpp.in ../cmake/ukui-build-tools/modules/UKUiAppTranslationLoader.cpp.in UKUiAppTranslationLoader.cpp @ONLY ) set(${source_files} ${${source_files}} ${CMAKE_CURRENT_BINARY_DIR}/UKUiAppTranslationLoader.cpp PARENT_SCOPE) endfunction() # ukui_lib_translation_loader( ) # The generated .cpp file is added to # Translations catalog to be loaded function(ukui_lib_translation_loader source_files catalog_name) configure_file( #${UKUI_CMAKE_MODULES_DIR}/UKUiLibTranslationLoader.cpp.in ../cmake/ukui-build-tools/modules/UKUiLibTranslationLoader.cpp.in UKUiLibTranslationLoader.cpp @ONLY ) set(${source_files} ${${source_files}} ${CMAKE_CURRENT_BINARY_DIR}/UKUiLibTranslationLoader.cpp PARENT_SCOPE) endfunction() # ukui_plugin_translation_loader( ) # The generated .cpp file is added to # Translations catalog to be loaded # Plugin type. Example: ukui-panel function(ukui_plugin_translation_loader source_files catalog_name plugin_type) configure_file( #${UKUI_CMAKE_MODULES_DIR}/UKUiPluginTranslationLoader.cpp.in #/usr/share/cmake/ukui-build-tools/modules/UKUiPluginTranslationLoader.cpp.in ../cmake/ukui-build-tools/modules/UKUiPluginTranslationLoader.cpp.in UKUiPluginTranslationLoader.cpp @ONLY ) set(${source_files} ${${source_files}} ${CMAKE_CURRENT_BINARY_DIR}/UKUiPluginTranslationLoader.cpp PARENT_SCOPE) endfunction() ukui-panel-3.0.6.4/cmake/ukui-build-tools/modules/Qt5TranslationLoader.cpp.in0000644000175000017500000000213114203402514025434 0ustar fengfeng/* This file has been generated by the CMake qt_translation_loader(). * It loads Qt application translations. * * Attention: All changes will be overwritten!!! */ #include #include #include #include #include static void loadQtTranslation() { QString locale = QLocale::system().name(); QTranslator *qtTranslator = new QTranslator(qApp); if (qtTranslator->load(QLatin1String("qt_") + locale, QLibraryInfo::location(QLibraryInfo::TranslationsPath))) { qApp->installTranslator(qtTranslator); } else { delete qtTranslator; } QTranslator *appTranslator = new QTranslator(qApp); if (appTranslator->load(QString::fromLocal8Bit("@translations_dir@/@catalog_name@_%1.qm").arg(locale))) { QCoreApplication::installTranslator(appTranslator); } else if (locale == QLatin1String("C") || locale.startsWith(QLatin1String("en"))) { // English is the default. It's translated anyway. delete appTranslator; } } Q_COREAPP_STARTUP_FUNCTION(loadQtTranslation) ukui-panel-3.0.6.4/cmake/ukui-build-tools/modules/Qt5PatchedLinguistToolsMacros.cmake0000644000175000017500000001130014203402514027153 0ustar fengfeng#============================================================================= # Copyright 2005-2011 Kitware, Inc. # Copyright (c) 2019 Tianjin KYLIN Information Technology Co., Ltd. * # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # * Neither the name of Kitware, Inc. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #============================================================================= include(CMakeParseArguments) function(QT5_PATCHED_CREATE_TRANSLATION _qm_files) set(options) set(oneValueArgs) set(multiValueArgs OPTIONS) cmake_parse_arguments(_LUPDATE "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) set(_lupdate_files ${_LUPDATE_UNPARSED_ARGUMENTS}) set(_lupdate_options ${_LUPDATE_OPTIONS}) set(_my_sources) set(_my_tsfiles) foreach(_file ${_lupdate_files}) get_filename_component(_ext ${_file} EXT) get_filename_component(_abs_FILE ${_file} ABSOLUTE) if(_ext MATCHES "ts") list(APPEND _my_tsfiles ${_abs_FILE}) else() list(APPEND _my_sources ${_abs_FILE}) endif() endforeach() foreach(_ts_file ${_my_tsfiles}) if(_my_sources) # make a list file to call lupdate on, so we don't make our commands too # long for some systems # get_filename_component(_ts_name ${_ts_file} NAME_WE) get_filename_component(_name ${_ts_file} NAME) string(REGEX REPLACE "^(.+)(\\.[^.]+)$" "\\1" _ts_name ${_name}) set(_ts_lst_file "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${_ts_name}_lst_file") set(_lst_file_srcs) foreach(_lst_file_src ${_my_sources}) set(_lst_file_srcs "${_lst_file_src}\n${_lst_file_srcs}") endforeach() get_directory_property(_inc_DIRS INCLUDE_DIRECTORIES) foreach(_pro_include ${_inc_DIRS}) get_filename_component(_abs_include "${_pro_include}" ABSOLUTE) set(_lst_file_srcs "-I${_pro_include}\n${_lst_file_srcs}") endforeach() file(WRITE ${_ts_lst_file} "${_lst_file_srcs}") endif() add_custom_command(OUTPUT ${_ts_file} COMMAND ${Qt5_LUPDATE_EXECUTABLE} ARGS ${_lupdate_options} "@${_ts_lst_file}" -ts ${_ts_file} DEPENDS ${_my_sources} ${_ts_lst_file} VERBATIM) endforeach() qt5_patched_add_translation(${_qm_files} ${_my_tsfiles}) set(${_qm_files} ${${_qm_files}} PARENT_SCOPE) endfunction() function(QT5_PATCHED_ADD_TRANSLATION _qm_files) foreach(_current_FILE ${ARGN}) get_filename_component(_abs_FILE ${_current_FILE} ABSOLUTE) # get_filename_component(qm ${_abs_FILE} NAME_WE) get_filename_component(_name ${_abs_FILE} NAME) string(REGEX REPLACE "^(.+)(\\.[^.]+)$" "\\1" qm ${_name}) get_source_file_property(output_location ${_abs_FILE} OUTPUT_LOCATION) if(output_location) file(MAKE_DIRECTORY "${output_location}") set(qm "${output_location}/${qm}.qm") else() set(qm "${CMAKE_CURRENT_BINARY_DIR}/${qm}.qm") endif() add_custom_command(OUTPUT ${qm} COMMAND ${Qt5_LRELEASE_EXECUTABLE} ARGS ${_abs_FILE} -qm ${qm} DEPENDS ${_abs_FILE} VERBATIM ) list(APPEND ${_qm_files} ${qm}) endforeach() set(${_qm_files} ${${_qm_files}} PARENT_SCOPE) endfunction() ukui-panel-3.0.6.4/cmake/ukui-build-tools/modules/UKUiCreatePortableHeaders.cmake0000644000175000017500000001037414203402514026244 0ustar fengfeng#============================================================================= # Copyright 2015 Luís Pereira # Copyright (c) 2019 Tianjin KYLIN Information Technology Co., Ltd. * # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # 1. Redistributions of source code must retain the copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # 3. The name of the author may not be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #============================================================================= # ukui_create_portable_headers( # HEADER_NAMES [ [...]] # [OUTPUT_DIR ] # ) # # Creates portable headers; e.g.: # Creates XdgAction from xdgaction.h # XdgAction contents: # #include "xdgaction.h" # # Output: # portable_headers File locations of the created headers # # Input: # HEADER_NAMES Header CamelCaseNames. An CamelCaseName header will be created # that includes camelcasename.h file # # OUTPUT_DIR Specifies where the files will be created. Defaults to # ``${CMAKE_CURRENT_BINARY_DIR}``. If the value is an relative path, it # will be appended to ``${CMAKE_CURRENT_BINARY_DIR}``. # # Use: # set(PUBLIC_CLASSES MyClass YourClass) # ukui_create_portable_headers(PORTABLE_HEADERS ${PUBLIC_CLASSES}) # PORTABLE_HEADER is an return value that contains the full name of the # generated headers. function(ukui_create_portable_headers outfiles) set(options) set(oneValueArgs OUTPUT_DIR PATH_PREFIX NAME_PREFIX) set(multiValueArgs HEADER_NAMES) cmake_parse_arguments(USER "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) if (USER_UNPARSED_ARGUMENTS) message(FATAL_ERROR "Unknown keywords given to ukui_create_portable_headers(): \"${USER_UNPARSED_ARGUMENTS}\"") endif() if (NOT DEFINED USER_HEADER_NAMES) message(FATAL_ERROR "Required argument HEADER_NAMES missing in ukui_create_portable_headers() call") else() set(_HEADER_NAMES "${USER_HEADER_NAMES}") endif() if (NOT DEFINED USER_OUTPUT_DIR) set(_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}") else() if (IS_ABSOLUTE "${USER_OUTPUT_DIR}") set(_OUTPUT_DIR "${USER_OUTPUT_DIR}") else() set(_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/${USER_OUTPUT_DIR}") endif() endif() if (NOT DEFINED USER_PATH_PREFIX) set(_PATH_PREFIX "") else() set(_PATH_PREFIX "${USER_PATH_PREFIX}") endif() if (NOT DEFINED USER_NAME_PREFIX) set(_NAME_PREFIX "") else() set(_NAME_PREFIX "${USER_NAME_PREFIX}") endif() set(class_list ${_HEADER_NAMES}) foreach(f ${class_list}) string(TOLOWER "${f}.h" _filename) if ("${_PATH_PREFIX}" STREQUAL "") file(WRITE "${_OUTPUT_DIR}/${f}" "#include \"${_NAME_PREFIX}${_filename}\"") else() file(WRITE "${_OUTPUT_DIR}/${f}" "#include \"${_PATH_PREFIX}${_NAME_PREFIX}/${_filename}\"") endif() list(APPEND ${outfiles} "${_OUTPUT_DIR}/${f}") endforeach() set(${outfiles} ${${outfiles}} PARENT_SCOPE) endfunction() ukui-panel-3.0.6.4/cmake/ukui-build-tools/modules/UKUiCreatePkgConfigFile.cmake0000644000175000017500000002077614203402514025656 0ustar fengfeng#============================================================================= # Copyright 2015 Luís Pereira # Copyright (c) 2019 Tianjin KYLIN Information Technology Co., Ltd. * # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # 1. Redistributions of source code must retain the copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # 3. The name of the author may not be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #=============================================================================# # ukui_create_pkgconfig_file(PACKAGE_NAME # VERSION # [PREFIX ] # [EXEC_PREFIX ] # [INCLUDEDIR_PREFIX ] # [INCLUDEDIRS ... ] # [LIBDIR_PREFIX ] # [DESCRIPTIVE_NAME ] # [DESCRIPTION ] # [URL ] # [REQUIRES ... ] # [REQUIRES_PRIVATE ... ] # [LIB_INSTALLDIR ] # [CFLAGS ] # [PATH ] # [INSTALL] # [COMPONENT] component) # # # PACKAGE_NAME and VERSION are mandatory. Everything else is optional include(CMakeParseArguments) include(GNUInstallDirs) function(ukui_create_pkgconfig_file) set(options INSTALL) set(oneValueArgs PACKAGE_NAME PREFIX EXEC_PREFIX INCLUDEDIR_PREFIX LIBDIR_PREFIX DESCRIPTIVE_NAME DESCRIPTION URL VERSION PATH COMPONENT ) set(multiValueArgs INCLUDEDIRS REQUIRES REQUIRES_PRIVATE CONFLICTS CFLAGS LIBS LIBS_PRIVATE ) cmake_parse_arguments(USER "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) if (USER_UNPARSED_ARGUMENTS) message(FATAL_ERROR "Unknown keywords given to create_pkgconfig_file(): \"${USER_UNPARSED_ARGUMENTS}\"") endif() # Check for mandatory args. Abort if not set if (NOT DEFINED USER_PACKAGE_NAME) message(FATAL_ERROR "Required argument PACKAGE_NAME missing in generate_pkgconfig_file() call") else() set(_PKGCONFIG_PACKAGE_NAME "${USER_PACKAGE_NAME}") endif() if (NOT DEFINED USER_VERSION) message(FATAL_ERROR "Required argument VERSION missing in generate_pkgconfig_file() call") else() set(_PKGCONFIG_VERSION "${USER_VERSION}") endif() # Optional args if (NOT DEFINED USER_PREFIX) set(_PKGCONFIG_PREFIX "${CMAKE_INSTALL_PREFIX}") endif() if (NOT DEFINED USER_EXEC_PREFIX) set(_PKGCONFIG_EXEC_PREFIX "\${prefix}") endif() if (NOT DEFINED USER_INCLUDEDIR_PREFIX) set(_PKGCONFIG_INCLUDEDIR_PREFIX "\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}") endif() if (NOT DEFINED USER_LIBDIR_PREFIX) set(_PKGCONFIG_LIBDIR_PREFIX "\${prefix}/${CMAKE_INSTALL_LIBDIR}") endif() if (NOT DEFINED USER_DESCRIPTIVE_NAME) set(_PKGCONFIG_DESCRIPTIVE_NAME "") else() set(_PKGCONFIG_DESCRIPTIVE_NAME "${USER_DESCRIPTIVE_NAME}") endif() if (DEFINED USER_INCLUDEDIRS) set(tmp "") foreach(dir ${USER_INCLUDEDIRS}) if (NOT IS_ABSOLUTE "${dir}") list(APPEND tmp "-I\${includedir}/${dir}") endif() endforeach() string(REPLACE ";" " " _INCLUDEDIRS "${tmp}") endif() if (DEFINED USER_REQUIRES) string(REPLACE ";" ", " _PKGCONFIG_REQUIRES "${USER_REQUIRES}") endif() if (DEFINED USER_REQUIRES_PRIVATE) string(REPLACE ";" ", " _PKGCONFIG_REQUIRES_PRIVATE "${USER_REQUIRES_PRIVATE}") else() set(_PKGCONFIG_REQUIRES_PRIVATE "") endif() if (NOT DEFINED USER_CFLAGS) set(_PKGCONFIG_CFLAGS "-I\${includedir} ${_INCLUDEDIRS}") endif() if (NOT DEFINED USER_LIBS) set(_PKGCONFIG_LIBS "-L\${libdir}") else() set(tmp "-L\${libdir}") set(_libs "${USER_LIBS}") foreach(lib ${_libs}) list(APPEND tmp "-l${lib}") endforeach() string(REPLACE ";" " " _PKGCONFIG_LIBS "${tmp}") endif() if (NOT DEFINED USER_LIBS_PRIVATE) set(PKGCONFIG_LIBS "-L\${libdir}") else() set(tmp "") set(_libs "${USER_LIBS_PRIVATE}") foreach(lib ${_libs}) list(APPEND tmp "-l${lib}") endforeach() string(REPLACE ";" " " _PKGCONFIG_LIBS_PRIVATE "${tmp}") endif() if (DEFINED USER_DESCRIPTION) set(_PKGCONFIG_DESCRIPTION "${USER_DESCRIPTION}") else() set(_PKGCONFIG_DESCRIPTION "") endif() if (DEFINED USER_URL) set(_PKFCONFIG_URL "${USER_URL}") else() set(_PKGCONFIG_URL "") endif() if (NOT DEFINED USER_PATH) set(_PKGCONFIG_FILE "${PROJECT_BINARY_DIR}/${_PKGCONFIG_PACKAGE_NAME}.pc") else() if (IS_ABSOLUTE "${USER_PATH}") set(_PKGCONFIG_FILE "${USER_PATH}/${_PKGCONFIG_PACKAGE_NAME}.pc") else() set(_PKGCONFIG_FILE "${PROJECT_BINARY_DIR}/${USER_PATH}/${_PKGCONFIG_PACKAGE_NAME}.pc") endif() endif() # Write the .pc file FILE(WRITE "${_PKGCONFIG_FILE}" "# file generated by create_pkgconfig_file()\n" "prefix=${_PKGCONFIG_PREFIX}\n" "exec_prefix=${_PKGCONFIG_EXEC_PREFIX}\n" "libdir=${_PKGCONFIG_LIBDIR_PREFIX}\n" "includedir=${_PKGCONFIG_INCLUDEDIR_PREFIX}\n" "\n" "Name: ${_PKGCONFIG_DESCRIPTIVE_NAME}\n" ) if (NOT "${_PKGCONFIG_DESCRIPTION}" STREQUAL "") FILE(APPEND ${_PKGCONFIG_FILE} "Description: ${_PKGCONFIG_DESCRIPTION}\n" ) endif() if (NOT "${_PKGCONFIG_URL}" STREQUAL "") FILE(APPEND ${_PKGCONFIG_FILE} "URL: ${_PKGCONFIG_URL}\n") endif() FILE(APPEND ${_PKGCONFIG_FILE} "Version: ${_PKGCONFIG_VERSION}\n") if (NOT "${_PKGCONFIG_REQUIRES}" STREQUAL "") FILE(APPEND ${_PKGCONFIG_FILE} "Requires: ${_PKGCONFIG_REQUIRES}\n") endif() if (NOT "${_PKGCONFIG_REQUIRES_PRIVATE}" STREQUAL "") FILE(APPEND ${_PKGCONFIG_FILE} "Requires.private: ${_PKGCONFIG_REQUIRES_PRIVATE}\n" ) endif() FILE(APPEND ${_PKGCONFIG_FILE} "Cflags: ${_PKGCONFIG_CFLAGS}\n" "Libs: ${_PKGCONFIG_LIBS}\n" ) if (NOT "${_PKGCONFIG_LIBS_PRIVATE}" STREQUAL "") FILE(APPEND ${_PKGCONFIG_FILE} "Libs.private: ${_PKGCONFIG_REQUIRES_PRIVATE}\n" ) endif() if (DEFINED USER_INSTALL) # FreeBSD loves to install files to different locations # https://www.freebsd.org/doc/handbook/dirstructure.html if(${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD") set(_PKGCONFIG_INSTALL_DESTINATION "libdata/pkgconfig") else() set(_PKGCONFIG_INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig") endif() if (DEFINED USER_COMPONENT) set(_COMPONENT "${USER_COMPONENT}") else() set(_COMPONENT "Devel") endif() install(FILES "${_PKGCONFIG_FILE}" DESTINATION "${_PKGCONFIG_INSTALL_DESTINATION}" COMPONENT "${_COMPONENT}") endif() endfunction() ukui-panel-3.0.6.4/cmake/ukui-build-tools/modules/Qt5TranslationLoader.cmake0000644000175000017500000000464614203402514025342 0ustar fengfeng#============================================================================= # Copyright 2014 Luís Pereira # Copyright (c) 2019 Tianjin KYLIN Information Technology Co., Ltd. * # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # 1. Redistributions of source code must retain the copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # 3. The name of the author may not be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #============================================================================= # # These functions enables "automatic" translation loading in Qt5 apps # and libs. They generate a .cpp file that takes care of everything. The # user doesn't have to do anything in the source code. # # qt5_translation_loader( ) # # Output: # Appends the generated file to this variable. # # Input: # Full path name to the translations dir. # Translation catalog to be loaded. function(qt5_translation_loader source_files translations_dir catalog_name) configure_file( ${UKUI_CMAKE_MODULES_DIR}/Qt5TranslationLoader.cpp.in Qt5TranslationLoader.cpp @ONLY ) set(${source_files} ${${source_files}} ${CMAKE_CURRENT_BINARY_DIR}/Qt5TranslationLoader.cpp PARENT_SCOPE) endfunction() ukui-panel-3.0.6.4/cmake/ukui-build-tools/modules/UKUiConfigVars.cmake0000644000175000017500000000343514203402514024115 0ustar fengfeng# The module defines the following variables # # UKUI_SHARE_DIR - This allows to install and read the configs from non-standard locations # # UKUI_TRANSLATIONS_DIR - The default translations directory # # UKUI_ETC_XDG_DIR - XDG standards expects system-wide configuration files in the # /etc/xdg/ukui location. Unfortunately QSettings we are using internally # can be overriden in the Qt compilation time to use different path for # system-wide configs. (for example configure ... -sysconfdir /etc/settings ...) # This path can be found calling Qt's qmake: # qmake -query QT_INSTALL_CONFIGURATION # # UKUI_DATA_DIR - UKUi base directory relative to which data files should # be searched.Defaults to CMAKE_INSTALL_FULL_DATADIR. It's # added to XDG_DATA_DIRS by the startukui script. set(UKUI_LIBRARY_NAME "ukui") set(UKUI_RELATIVE_SHARE_DIR "ukui") set(UKUI_SHARE_DIR "/usr/share/ukui") set(UKUI_RELATIVE_TRANSLATIONS_DIR "ukui/translations") set(UKUI_TRANSLATIONS_DIR "/usr/share/ukui/translations") set(UKUI_GRAPHICS_DIR "/usr/share/ukui/graphics") set(UKUI_ETC_XDG_DIR "/etc/xdg") set(UKUI_DATA_DIR "/usr/share") add_definitions("-DUKUI_RELATIVE_SHARE_DIR=\"${UKUI_RELATIVE_SHARE_DIR}\"") add_definitions("-DUKUI_SHARE_DIR=\"${UKUI_SHARE_DIR}\"") add_definitions("-DUKUI_RELATIVE_SHARE_TRANSLATIONS_DIR=\"${UKUI_RELATIVE_TRANSLATIONS_DIR}\"") add_definitions("-DUKUI_SHARE_TRANSLATIONS_DIR=\"${UKUI_TRANSLATIONS_DIR}\"") add_definitions("-DUKUI_GRAPHICS_DIR=\"${UKUI_GRAPHICS_DIR}\"") add_definitions("-DUKUI_ETC_XDG_DIR=\"${UKUI_ETC_XDG_DIR}\"") add_definitions("-DUKUI_DATA_DIR=\"${UKUI_DATA_DIR}\"") ukui-panel-3.0.6.4/cmake/ukui-build-tools/modules/UKUiTranslate.cmake0000644000175000017500000000366114203402514024012 0ustar fengfeng#============================================================================= # Copyright 2014 Luís Pereira # Copyright (c) 2019 Tianjin KYLIN Information Technology Co., Ltd. * # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # 1. Redistributions of source code must retain the copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # 3. The name of the author may not be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #============================================================================= # # An convenience module that loads all the UKUi translations modules at once. include(/usr/share/cmake/ukui-build-tools/modules/UKUiTranslateTs.cmake) include(/usr/share/cmake/ukui-build-tools/modules/UKUiTranslateDesktop.cmake) include(/usr/share/cmake/ukui-build-tools/modules/UKUiTranslationLoader.cmake) ukui-panel-3.0.6.4/cmake/ukui-build-tools/modules/UKUiAppTranslationLoader.cpp.in0000644000175000017500000000063414203402514026247 0ustar fengfeng/* This file has been generated by the CMake ukui_app_translation_loader(). * It loads UKUi application translations. * * Attention: All changes will be overwritten!!! */ #include #include "../panel/common/ukuitranslator.h" static void loadAppTranslation() { UKUi::Translator::translateApplication(QStringLiteral("@catalog_name@")); } Q_COREAPP_STARTUP_FUNCTION(loadAppTranslation) ukui-panel-3.0.6.4/cmake/ukui-build-tools/modules/UKUiCompilerSettings.cmake0000644000175000017500000001771114203402514025351 0ustar fengfeng#============================================================================= # Copyright 2015 Luís Pereira # Copyright 2015 Palo Kisa # Copyright 2013 Hong Jen Yee (PCMan) # Copyright (c) 2019 Tianjin KYLIN Information Technology Co., Ltd. * # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # 1. Redistributions of source code must retain the copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # 3. The name of the author may not be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #============================================================================= #----------------------------------------------------------------------------- # Build with release mode by default (turn on compiler optimizations) #----------------------------------------------------------------------------- if (NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE Release) endif() #----------------------------------------------------------------------------- # Honor visibility properties for all target types. # # The ``_VISIBILITY_PRESET`` and # ``VISIBILITY_INLINES_HIDDEN`` target properties affect visibility # of symbols during dynamic linking. When first introduced these properties # affected compilation of sources only in shared libraries, module libraries, # and executables with the ``ENABLE_EXPORTS`` property set. This # was sufficient for the basic use cases of shared libraries and executables # with plugins. However, some sources may be compiled as part of static # libraries or object libraries and then linked into a shared library later. # CMake 3.3 and above prefer to honor these properties for sources compiled # in all target types. This policy preserves compatibility for projects # expecting the properties to work only for some target types. # # The ``OLD`` behavior for this policy is to ignore the visibility properties # for static libraries, object libraries, and executables without exports. # The ``NEW`` behavior for this policy is to honor the visibility properties # for all target types. # # This policy was introduced in CMake version 3.3. CMake version # 3.3.0 warns when the policy is not set and uses ``OLD`` behavior. Use # the ``cmake_policy()`` command to set it to ``OLD`` or ``NEW`` # explicitly. #----------------------------------------------------------------------------- if(COMMAND CMAKE_POLICY) if (POLICY CMP0063) cmake_policy(SET CMP0063 NEW) endif() endif() include(CheckCXXCompilerFlag) #----------------------------------------------------------------------------- # Global definitions #----------------------------------------------------------------------------- add_definitions( -DQT_USE_QSTRINGBUILDER -DQT_NO_FOREACH ) if (CMAKE_BUILD_TYPE MATCHES "Debug") add_definitions(-DQT_STRICT_ITERATORS) endif() #----------------------------------------------------------------------------- # Detect Clang compiler #----------------------------------------------------------------------------- if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") set(UKUI_COMPILER_IS_CLANGCXX 1) endif() #----------------------------------------------------------------------------- # Set visibility to hidden to hide symbols, unless they're exported manually # in the code #----------------------------------------------------------------------------- set(CMAKE_C_VISIBILITY_PRESET hidden) set(CMAKE_CXX_VISIBILITY_PRESET hidden) set(CMAKE_VISIBILITY_INLINES_HIDDEN 1) #----------------------------------------------------------------------------- # Disable exceptions #----------------------------------------------------------------------------- if (CMAKE_COMPILER_IS_GNUCXX OR UKUI_COMPILER_IS_CLANGCXX) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions") endif() #----------------------------------------------------------------------------- # Common warning flags #----------------------------------------------------------------------------- set(__UKUI_COMMON_WARNING_FLAGS "-Wall -Wextra -Wchar-subscripts -Wno-long-long -Wpointer-arith -Wundef -Wformat-security") #----------------------------------------------------------------------------- # Warning flags #----------------------------------------------------------------------------- if (CMAKE_COMPILER_IS_GNUCXX OR UKUI_COMPILER_IS_CLANGCXX) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${__UKUI_COMMON_WARNING_FLAGS} -Wnon-virtual-dtor -Woverloaded-virtual -Wpedantic") endif() if (UKUI_COMPILER_IS_CLANGCXX) # qCDebug(), qCWarning, etc trigger a very verbose warning, about.... nothing. Disable it. # Found when building ukui-session. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-gnu-zero-variadic-macro-arguments") endif() #----------------------------------------------------------------------------- # Linker flags # Do not allow undefined symbols #----------------------------------------------------------------------------- if (CMAKE_COMPILER_IS_GNUCXX OR UKUI_COMPILER_IS_CLANGCXX) # -Bsymbolic-functions: replace dynamic symbols used internally in # shared libs with direct addresses. set(SYMBOLIC_FLAGS "-Wl,-Bsymbolic-functions -Wl,-Bsymbolic" ) set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--no-undefined ${SYMBOLIC_FLAGS} ${CMAKE_SHARED_LINKER_FLAGS}" ) set(CMAKE_MODULE_LINKER_FLAGS "-Wl,--no-undefined ${SYMBOLIC_FLAGS} ${CMAKE_MODULE_LINKER_FLAGS}" ) set(CMAKE_EXE_LINKER_FLAGS "${SYMBOLIC_FLAGS} ${CMAKE_EXE_LINKER_FLAGS}" ) endif() #----------------------------------------------------------------------------- # CXX14 requirements - no checks, we just set it #----------------------------------------------------------------------------- set(CMAKE_CXX_STANDARD_REQUIRED True) set(CMAKE_CXX_STANDARD 14 CACHE STRING "C++ ISO Standard") #----------------------------------------------------------------------------- # Enable colored diagnostics for the CLang/Ninja combination #----------------------------------------------------------------------------- if (CMAKE_GENERATOR STREQUAL "Ninja" AND # Rationale: https://public.kitware.com/Bug/view.php?id=15502 ((CMAKE_COMPILER_IS_GNUCXX AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.9) OR (UKUI_COMPILER_IS_CLANGCXX AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.5))) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fdiagnostics-color=always") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdiagnostics-color=always") endif() #----------------------------------------------------------------------------- # Enable exceptions for an target # # ukui_enable_target_exceptions( # # ) # #----------------------------------------------------------------------------- function(ukui_enable_target_exceptions target mode) target_compile_options(${target} ${mode} "$<$,$>:-fexceptions>" ) endfunction() ukui-panel-3.0.6.4/cmake/ukui-build-tools/modules/UKUiLibTranslationLoader.cpp.in0000644000175000017500000000060514203402514026233 0ustar fengfeng/* This file has been generated by the CMake ukui_app_translation_loader(). * It loads UKUi libraries translations. * * Attention: All changes will be overwritten!!! */ #include #include static void loadLibTranslation() { UKUi::Translator::translateLibrary(QStringLiteral("@catalog_name@")); } Q_COREAPP_STARTUP_FUNCTION(loadLibTranslation) ukui-panel-3.0.6.4/cmake/ukui-build-tools/modules/UKUiTranslateDesktop.cmake0000644000175000017500000000753114203402514025344 0ustar fengfeng#============================================================================= # The ukui_translate_desktop() function was copied from the # UKUi UKUiTranslate.cmake # # Original Author: Alexander Sokolov # # funtion ukui_translate_desktop(_RESULT # SOURCES # [TRANSLATION_DIR] translation_directory # ) # Output: # _RESULT The generated .desktop (.desktop) files # # Input: # # SOURCES List of input desktop files (.destktop.in) to be translated # (merged), relative to the CMakeList.txt. # # TRANSLATION_DIR Optional path to the directory with the .ts files, # relative to the CMakeList.txt. Defaults to # "translations". # #============================================================================= function(ukui_translate_desktop _RESULT) # Parse arguments *************************************** set(oneValueArgs TRANSLATION_DIR) set(multiValueArgs SOURCES) cmake_parse_arguments(_ARGS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) # check for unknown arguments set(_UNPARSED_ARGS ${_ARGS_UNPARSED_ARGUMENTS}) if (NOT ${_UNPARSED_ARGS} STREQUAL "") MESSAGE(FATAL_ERROR "Unknown arguments '${_UNPARSED_ARGS}'.\n" "See ukui_translate_desktop() documentation for more information.\n" ) endif() if (NOT DEFINED _ARGS_SOURCES) set(${_RESULT} "" PARENT_SCOPE) return() else() set(_sources ${_ARGS_SOURCES}) endif() if (NOT DEFINED _ARGS_TRANSLATION_DIR) set(_translationDir "translations") else() set(_translationDir ${_ARGS_TRANSLATION_DIR}) endif() get_filename_component (_translationDir ${_translationDir} ABSOLUTE) foreach (_inFile ${_sources}) get_filename_component(_inFile ${_inFile} ABSOLUTE) get_filename_component(_fileName ${_inFile} NAME_WE) #Extract the real extension ............ get_filename_component(_fileExt ${_inFile} EXT) string(REPLACE ".in" "" _fileExt ${_fileExt}) #....................................... set(_outFile "${CMAKE_CURRENT_BINARY_DIR}/${_fileName}${_fileExt}") file(GLOB _translations ${_translationDir}/${_fileName}_*${_fileExt} ) set(_pattern "'\\[.*]\\s*='") if (_translations) list(SORT _translations) add_custom_command(OUTPUT ${_outFile} COMMAND grep -v -a "'#TRANSLATIONS_DIR='" ${_inFile} > ${_outFile} COMMAND grep -h -a ${_pattern} ${_translations} >> ${_outFile} COMMENT "Generating ${_fileName}${_fileExt}" ) else() add_custom_command(OUTPUT ${_outFile} COMMAND grep -v -a "'#TRANSLATIONS_DIR='" ${_inFile} > ${_outFile} COMMENT "Generating ${_fileName}${_fileExt}" ) endif() set(__result ${__result} ${_outFile}) # TX file *********************************************** set(_txFile "${CMAKE_BINARY_DIR}/tx/${_fileName}${_fileExt}.tx.sh") string(REPLACE "${CMAKE_SOURCE_DIR}/" "" _tx_translationDir ${_translationDir}) string(REPLACE "${CMAKE_SOURCE_DIR}/" "" _tx_inFile ${_inFile}) string(REPLACE "." "" _fileType ${_fileExt}) file(WRITE ${_txFile} "[ -f ${_inFile} ] || exit 0\n" "echo '[ukui.${_fileName}_${_fileType}]'\n" "echo 'type = DESKTOP'\n" "echo 'source_lang = en'\n" "echo 'source_file = ${_tx_inFile}'\n" "echo 'file_filter = ${_tx_translationDir}/${_fileName}_${_fileExt}'\n" "echo ''\n" ) endforeach() set(${_RESULT} ${__result} PARENT_SCOPE) endfunction(ukui_translate_desktop) ukui-panel-3.0.6.4/cmake/ukui-build-tools/modules/UKUiTranslateTs.cmake0000644000175000017500000001320514203402514024314 0ustar fengfeng#============================================================================= # Copyright 2014 Luís Pereira # Copyright (c) 2019 Tianjin KYLIN Information Technology Co., Ltd. * # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # 1. Redistributions of source code must retain the copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # 3. The name of the author may not be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #============================================================================= # # funtion ukui_translate_ts(qmFiles # [USE_QT5 [Yes | No]] # [UPDATE_TRANSLATIONS [Yes | No]] # SOURCES # [UPDATE_OPTIONS] update_options # [TEMPLATE] translation_template # [TRANSLATION_DIR] translation_directory # [INSTALL_DIR] install_directory # [COMPONENT] component # ) # Output: # qmFiles The generated compiled translations (.qm) files # # Input: # USE_QT5 Optional flag to choose between Qt4 and Qt5. Defaults to Qt5 # # UPDATE_TRANSLATIONS Optional flag. Setting it to Yes, extracts and # compiles the translations. Setting it No, only # compiles them. # # UPDATE_OPTIONS Optional options to lupdate when UPDATE_TRANSLATIONS # is True. # # TEMPLATE Optional translations files base name. Defaults to # ${PROJECT_NAME}. An .ts extensions is added. # # TRANSLATION_DIR Optional path to the directory with the .ts files, # relative to the CMakeList.txt. Defaults to # "translations". # # INSTALL_DIR Optional destination of the file compiled files (qmFiles). # If not present no installation is performed # # COMPONENT Optional install component. Only effective if INSTALL_DIR # present. Defaults to "Runtime". # # We use our patched version to round a annoying bug. include(Qt5PatchedLinguistToolsMacros) function(ukui_translate_ts qmFiles) set(oneValueArgs USE_QT5 UPDATE_TRANSLATIONS TEMPLATE TRANSLATION_DIR INSTALL_DIR COMPONENT ) set(multiValueArgs SOURCES UPDATE_OPTIONS) cmake_parse_arguments(TR "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) if (NOT DEFINED TR_UPDATE_TRANSLATIONS) set(TR_UPDATE_TRANSLATIONS "No") endif() if (NOT DEFINED TR_UPDATE_OPTIONS) set(TR_UPDATE_OPTIONS "") endif() if (NOT DEFINED TR_USE_QT5) set(TR_USE_QT5 "Yes") endif() if(NOT DEFINED TR_TEMPLATE) set(TR_TEMPLATE "${PROJECT_NAME}") endif() if (NOT DEFINED TR_TRANSLATION_DIR) set(TR_TRANSLATION_DIR "translations") endif() get_filename_component(TR_TRANSLATION_DIR "${TR_TRANSLATION_DIR}" ABSOLUTE) if (EXISTS "${TR_TRANSLATION_DIR}") file(GLOB tsFiles "${TR_TRANSLATION_DIR}/${TR_TEMPLATE}_*.ts") set(templateFile "${TR_TRANSLATION_DIR}/${TR_TEMPLATE}.ts") endif () if(TR_USE_QT5) # Qt5 if (TR_UPDATE_TRANSLATIONS) qt5_patched_create_translation(QMS ${TR_SOURCES} ${templateFile} OPTIONS ${TR_UPDATE_OPTIONS} ) qt5_patched_create_translation(QM ${TR_SOURCES} ${tsFiles} OPTIONS ${TR_UPDATE_OPTIONS} ) else() qt5_patched_add_translation(QM ${tsFiles}) endif() else() # Qt4 if(TR_UPDATE_TRANSLATIONS) qt4_create_translation(QMS ${TR_SOURCES} ${templateFile} OPTIONS ${TR_UPDATE_OPTIONS} ) qt4_create_translation(QM ${TR_SOURCES} ${tsFiles} OPTIONS ${TR_UPDATE_OPTIONS} ) else() qt4_add_translation(QM ${tsFiles}) endif() endif() if(TR_UPDATE_TRANSLATIONS) add_custom_target("update_${TR_TEMPLATE}_ts" ALL DEPENDS ${QMS}) endif() if(DEFINED TR_INSTALL_DIR) if(NOT DEFINED TR_COMPONENT) set(TR_COMPONENT "Runtime") endif() install(FILES ${QM} DESTINATION "${TR_INSTALL_DIR}" COMPONENT "${TR_COMPONENT}" ) endif() set(${qmFiles} ${QM} PARENT_SCOPE) endfunction() ukui-panel-3.0.6.4/cmake/ukui-build-tools/modules/ECMFindModuleHelpers.cmake0000644000175000017500000003237014203402514025214 0ustar fengfeng#.rst: # ECMFindModuleHelpers # -------------------- # # Helper macros for find modules: ecm_find_package_version_check(), # ecm_find_package_parse_components() and # ecm_find_package_handle_library_components(). # # :: # # ecm_find_package_version_check() # # Prints warnings if the CMake version or the project's required CMake version # is older than that required by extra-cmake-modules. # # :: # # ecm_find_package_parse_components( # RESULT_VAR # KNOWN_COMPONENTS [ [...]] # [SKIP_DEPENDENCY_HANDLING]) # # This macro will populate with a list of components found in # _FIND_COMPONENTS, after checking that all those components are in the # list of KNOWN_COMPONENTS; if there are any unknown components, it will print # an error or warning (depending on the value of _FIND_REQUIRED) and call # return(). # # The order of components in is guaranteed to match the order they # are listed in the KNOWN_COMPONENTS argument. # # If SKIP_DEPENDENCY_HANDLING is not set, for each component the variable # __component_deps will be checked for dependent components. # If is listed in _FIND_COMPONENTS, then all its (transitive) # dependencies will also be added to . # # :: # # ecm_find_package_handle_library_components( # COMPONENTS [ [...]] # [SKIP_DEPENDENCY_HANDLING]) # [SKIP_PKG_CONFIG]) # # Creates an imported library target for each component. The operation of this # macro depends on the presence of a number of CMake variables. # # The __lib variable should contain the name of this library, # and __header variable should contain the name of a header # file associated with it (whatever relative path is normally passed to # '#include'). __header_subdir variable can be used to specify # which subdirectory of the include path the headers will be found in. # ecm_find_package_components() will then search for the library # and include directory (creating appropriate cache variables) and create an # imported library target named ::. # # Additional variables can be used to provide additional information: # # If SKIP_PKG_CONFIG, the __pkg_config variable is set, and # pkg-config is found, the pkg-config module given by # __pkg_config will be searched for and used to help locate the # library and header file. It will also be used to set # __VERSION. # # Note that if version information is found via pkg-config, # __FIND_VERSION can be set to require a particular version # for each component. # # If SKIP_DEPENDENCY_HANDLING is not set, the INTERFACE_LINK_LIBRARIES property # of the imported target for will be set to contain the imported # targets for the components listed in __component_deps. # _FOUND will also be set to false if any of the compoments in # __component_deps are not found. This requires the components # in __component_deps to be listed before in the # COMPONENTS argument. # # The following variables will be set: # # ``_TARGETS`` # the imported targets # ``_LIBRARIES`` # the found libraries # ``_INCLUDE_DIRS`` # the combined required include directories for the components # ``_DEFINITIONS`` # the "other" CFLAGS provided by pkg-config, if any # ``_VERSION`` # the value of ``__VERSION`` for the first component that # has this variable set (note that components are searched for in the order # they are passed to the macro), although if it is already set, it will not # be altered # # Note that these variables are never cleared, so if # ecm_find_package_handle_library_components() is called multiple times with # different components (typically because of multiple find_package() calls) then # ``_TARGETS``, for example, will contain all the targets found in any # call (although no duplicates). # # Since pre-1.0.0. #============================================================================= # Copyright 2014 Alex Merry # Copyright (c) 2019 Tianjin KYLIN Information Technology Co., Ltd. * # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # 1. Redistributions of source code must retain the copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # 3. The name of the author may not be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include(CMakeParseArguments) macro(ecm_find_package_version_check module_name) if(CMAKE_VERSION VERSION_LESS 3.1.0) message(FATAL_ERROR "CMake 3.1.0 is required by ukui-build-tools!") endif() if(CMAKE_MINIMUM_REQUIRED_VERSION VERSION_LESS 3.1.0) message(AUTHOR_WARNING "Your project should require at least CMake 3.1.0!") endif() endmacro() macro(ecm_find_package_parse_components module_name) set(ecm_fppc_options SKIP_DEPENDENCY_HANDLING) set(ecm_fppc_oneValueArgs RESULT_VAR) set(ecm_fppc_multiValueArgs KNOWN_COMPONENTS DEFAULT_COMPONENTS) cmake_parse_arguments(ECM_FPPC "${ecm_fppc_options}" "${ecm_fppc_oneValueArgs}" "${ecm_fppc_multiValueArgs}" ${ARGN}) if(ECM_FPPC_UNPARSED_ARGUMENTS) message(FATAL_ERROR "Unexpected arguments to ecm_find_package_parse_components: ${ECM_FPPC_UNPARSED_ARGUMENTS}") endif() if(NOT ECM_FPPC_RESULT_VAR) message(FATAL_ERROR "Missing RESULT_VAR argument to ecm_find_package_parse_components") endif() if(NOT ECM_FPPC_KNOWN_COMPONENTS) message(FATAL_ERROR "Missing KNOWN_COMPONENTS argument to ecm_find_package_parse_components") endif() if(NOT ECM_FPPC_DEFAULT_COMPONENTS) set(ECM_FPPC_DEFAULT_COMPONENTS ${ECM_FPPC_KNOWN_COMPONENTS}) endif() if(${module_name}_FIND_COMPONENTS) set(ecm_fppc_requestedComps ${${module_name}_FIND_COMPONENTS}) if(NOT ECM_FPPC_SKIP_DEPENDENCY_HANDLING) # Make sure deps are included foreach(ecm_fppc_comp ${ecm_fppc_requestedComps}) foreach(ecm_fppc_dep_comp ${${module_name}_${ecm_fppc_comp}_component_deps}) list(FIND ecm_fppc_requestedComps "${ecm_fppc_dep_comp}" ecm_fppc_index) if("${ecm_fppc_index}" STREQUAL "-1") if(NOT ${module_name}_FIND_QUIETLY) message(STATUS "${module_name}: ${ecm_fppc_comp} requires ${${module_name}_${ecm_fppc_comp}_component_deps}") endif() list(APPEND ecm_fppc_requestedComps "${ecm_fppc_dep_comp}") endif() endforeach() endforeach() else() message(STATUS "Skipping dependency handling for ${module_name}") endif() list(REMOVE_DUPLICATES ecm_fppc_requestedComps) # This makes sure components are listed in the same order as # KNOWN_COMPONENTS (potentially important for inter-dependencies) set(${ECM_FPPC_RESULT_VAR}) foreach(ecm_fppc_comp ${ECM_FPPC_KNOWN_COMPONENTS}) list(FIND ecm_fppc_requestedComps "${ecm_fppc_comp}" ecm_fppc_index) if(NOT "${ecm_fppc_index}" STREQUAL "-1") list(APPEND ${ECM_FPPC_RESULT_VAR} "${ecm_fppc_comp}") list(REMOVE_AT ecm_fppc_requestedComps ${ecm_fppc_index}) endif() endforeach() # if there are any left, they are unknown components if(ecm_fppc_requestedComps) set(ecm_fppc_msgType STATUS) if(${module_name}_FIND_REQUIRED) set(ecm_fppc_msgType FATAL_ERROR) endif() if(NOT ${module_name}_FIND_QUIETLY) message(${ecm_fppc_msgType} "${module_name}: requested unknown components ${ecm_fppc_requestedComps}") endif() return() endif() else() set(${ECM_FPPC_RESULT_VAR} ${ECM_FPPC_DEFAULT_COMPONENTS}) endif() endmacro() macro(ecm_find_package_handle_library_components module_name) set(ecm_fpwc_options SKIP_PKG_CONFIG SKIP_DEPENDENCY_HANDLING) set(ecm_fpwc_oneValueArgs) set(ecm_fpwc_multiValueArgs COMPONENTS) cmake_parse_arguments(ECM_FPWC "${ecm_fpwc_options}" "${ecm_fpwc_oneValueArgs}" "${ecm_fpwc_multiValueArgs}" ${ARGN}) if(ECM_FPWC_UNPARSED_ARGUMENTS) message(FATAL_ERROR "Unexpected arguments to ecm_find_package_handle_components: ${ECM_FPWC_UNPARSED_ARGUMENTS}") endif() if(NOT ECM_FPWC_COMPONENTS) message(FATAL_ERROR "Missing COMPONENTS argument to ecm_find_package_handle_components") endif() include(FindPackageHandleStandardArgs) find_package(PkgConfig) foreach(ecm_fpwc_comp ${ECM_FPWC_COMPONENTS}) set(ecm_fpwc_dep_vars) set(ecm_fpwc_dep_targets) if(NOT SKIP_DEPENDENCY_HANDLING) foreach(ecm_fpwc_dep ${${module_name}_${ecm_fpwc_comp}_component_deps}) list(APPEND ecm_fpwc_dep_vars "${module_name}_${ecm_fpwc_dep}_FOUND") list(APPEND ecm_fpwc_dep_targets "${module_name}::${ecm_fpwc_dep}") endforeach() endif() if(NOT ECM_FPWC_SKIP_PKG_CONFIG AND ${module_name}_${ecm_fpwc_comp}_pkg_config) pkg_check_modules(PKG_${module_name}_${ecm_fpwc_comp} ${${module_name}_${ecm_fpwc_comp}_pkg_config}) endif() find_path(${module_name}_${ecm_fpwc_comp}_INCLUDE_DIR NAMES ${${module_name}_${ecm_fpwc_comp}_header} HINTS ${PKG_${module_name}_${ecm_fpwc_comp}_INCLUDE_DIRS} PATH_SUFFIXES ${${module_name}_${ecm_fpwc_comp}_header_subdir} ) find_library(${module_name}_${ecm_fpwc_comp}_LIBRARY NAMES ${${module_name}_${ecm_fpwc_comp}_lib} HINTS ${PKG_${module_name}_${ecm_fpwc_comp}_LIBRARY_DIRS} ) set(${module_name}_${ecm_fpwc_comp}_VERSION "${PKG_${module_name}_${ecm_fpwc_comp}_VERSION}") if(NOT ${module_name}_VERSION) set(${module_name}_VERSION ${${module_name}_${ecm_fpwc_comp}_VERSION}) endif() find_package_handle_standard_args(${module_name}_${ecm_fpwc_comp} FOUND_VAR ${module_name}_${ecm_fpwc_comp}_FOUND REQUIRED_VARS ${module_name}_${ecm_fpwc_comp}_LIBRARY ${module_name}_${ecm_fpwc_comp}_INCLUDE_DIR ${ecm_fpwc_dep_vars} VERSION_VAR ${module_name}_${ecm_fpwc_comp}_VERSION ) mark_as_advanced( ${module_name}_${ecm_fpwc_comp}_LIBRARY ${module_name}_${ecm_fpwc_comp}_INCLUDE_DIR ) if(${module_name}_${ecm_fpwc_comp}_FOUND) list(APPEND ${module_name}_LIBRARIES "${${module_name}_${ecm_fpwc_comp}_LIBRARY}") list(APPEND ${module_name}_INCLUDE_DIRS "${${module_name}_${ecm_fpwc_comp}_INCLUDE_DIR}") set(${module_name}_DEFINITIONS ${${module_name}_DEFINITIONS} ${PKG_${module_name}_${ecm_fpwc_comp}_DEFINITIONS}) if(NOT TARGET ${module_name}::${ecm_fpwc_comp}) add_library(${module_name}::${ecm_fpwc_comp} UNKNOWN IMPORTED) set_target_properties(${module_name}::${ecm_fpwc_comp} PROPERTIES IMPORTED_LOCATION "${${module_name}_${ecm_fpwc_comp}_LIBRARY}" INTERFACE_COMPILE_OPTIONS "${PKG_${module_name}_${ecm_fpwc_comp}_DEFINITIONS}" INTERFACE_INCLUDE_DIRECTORIES "${${module_name}_${ecm_fpwc_comp}_INCLUDE_DIR}" INTERFACE_LINK_LIBRARIES "${ecm_fpwc_dep_targets}" ) endif() list(APPEND ${module_name}_TARGETS "${module_name}::${ecm_fpwc_comp}") endif() endforeach() if(${module_name}_LIBRARIES) list(REMOVE_DUPLICATES ${module_name}_LIBRARIES) endif() if(${module_name}_INCLUDE_DIRS) list(REMOVE_DUPLICATES ${module_name}_INCLUDE_DIRS) endif() if(${module_name}_DEFINITIONS) list(REMOVE_DUPLICATES ${module_name}_DEFINITIONS) endif() if(${module_name}_TARGETS) list(REMOVE_DUPLICATES ${module_name}_TARGETS) endif() endmacro() ukui-panel-3.0.6.4/cmake/ukui-build-tools/modules/UKUiPreventInSourceBuilds.cmake0000644000175000017500000000627414203402514026316 0ustar fengfeng#============================================================================= # Copyright (c) 2018 Luís Pereira # Copyright (c) 2019 Tianjin KYLIN Information Technology Co., Ltd. * # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # 1. Redistributions of source code must retain the copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # 3. The name of the author may not be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #============================================================================= function(ukui_prevent_in_source_builds) # Handle smarties with symlinks get_filename_component(srcdir "${CMAKE_SOURCE_DIR}" REALPATH) get_filename_component(bindir "${CMAKE_BINARY_DIR}" REALPATH) if("${srcdir}" STREQUAL "${bindir}") # We are in a in source build message("##############################################################") message("# In Source Build detected.") message("# UKUi does not support in source builds.") message("# Out of source build is required.") message("#") message("# The general approach to out of source builds is:") message("# mkdir build") message("# cd build") message("# cmake ") message("# make") message("#") message("# An in source build was attemped. Some files were created.") message("# Use 'git status' to check them. Remove them with:") message("# cd ") message("#") message("# # Don’t actually remove anything, just show what would be done") message("# git clean -n -d") message("#") message("# # Actually remove the files") message("# git clean -f -d") message("#") message("# checkout files out of the index") message("# git checkout --") message("##############################################################") message(FATAL_ERROR "Aborting configuration") endif() endfunction() ukui_prevent_in_source_builds() ukui-panel-3.0.6.4/cmake/ukui-build-tools/find-modules/0000755000175000017500000000000014203402514021225 5ustar fengfengukui-panel-3.0.6.4/cmake/ukui-build-tools/find-modules/FindXdgUserDirs.cmake0000644000175000017500000000456414203402514025244 0ustar fengfeng#============================================================================= # Copyright 2015 Luís Pereira # Copyright (c) 2019 Tianjin KYLIN Information Technology Co., Ltd. * # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # 1. Redistributions of source code must retain the copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # 3. The name of the author may not be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #============================================================================= # FindXdgUserDirs # # Try to find xdg-user-dirs-update. # # If the xdg-user-dirs-update executable is not in your PATH, you can provide # an alternative name or full path location with the # `XdgUserDirsUpdate_EXECUTABLE` variable. # # This will define the following variables: # # `XdgUserDirs_FOUND` # True if xdg-user-dirs-update is available. # # `XdgUserDirsUpdate_EXECUTABLE` # The xdg-user-dirs-update executable. # # Find xdg-user-dirs-update find_program(XdgUserDirsUpdate_EXECUTABLE NAMES xdg-user-dirs-update) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(XdgUserDirs FOUND_VAR XdgUserDirs_FOUND REQUIRED_VARS XdgUserDirsUpdate_EXECUTABLE ) mark_as_advanced(XdgUserDirsUpdate_EXECUTABLE) ukui-panel-3.0.6.4/cmake/ukui-build-tools/find-modules/FindGLIB.cmake0000644000175000017500000001304114203402514023544 0ustar fengfeng# - Try to find Glib and its components (gio, gobject etc) # Once done, this will define # # GLIB_FOUND - system has Glib # GLIB_INCLUDE_DIRS - the Glib include directories # GLIB_LIBRARIES - link these to use Glib # # Optionally, the COMPONENTS keyword can be passed to find_package() # and Glib components can be looked for. Currently, the following # components can be used, and they define the following variables if # found: # # gio: GLIB_GIO_LIBRARIES # gobject: GLIB_GOBJECT_LIBRARIES # gmodule: GLIB_GMODULE_LIBRARIES # gthread: GLIB_GTHREAD_LIBRARIES # # Note that the respective _INCLUDE_DIR variables are not set, since # all headers are in the same directory as GLIB_INCLUDE_DIRS. # # Copyright (C) 2012 Raphael Kubo da Costa # Copyright (C) 2016 Luís Pereira # Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND ITS CONTRIBUTORS ``AS # IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR ITS # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; # OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR # OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF # ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. find_package(PkgConfig) pkg_check_modules(PC_GLIB glib-2.0) find_library(GLIB_LIBRARIES NAMES glib-2.0 HINTS ${PC_GLIB_LIBDIR} ${PC_GLIB_LIBRARY_DIRS} ) # Files in glib's main include path may include glibconfig.h, which, # for some odd reason, is normally in $LIBDIR/glib-2.0/include. get_filename_component(_GLIB_LIBRARY_DIR ${GLIB_LIBRARIES} PATH) find_path(GLIBCONFIG_INCLUDE_DIR NAMES glibconfig.h HINTS ${PC_LIBDIR} ${PC_LIBRARY_DIRS} ${_GLIB_LIBRARY_DIR} ${PC_GLIB_INCLUDEDIR} ${PC_GLIB_INCLUDE_DIRS} PATH_SUFFIXES glib-2.0/include ) find_path(GLIB_INCLUDE_DIR NAMES glib.h HINTS ${PC_GLIB_INCLUDEDIR} ${PC_GLIB_INCLUDE_DIRS} PATH_SUFFIXES glib-2.0 ) set(GLIB_INCLUDE_DIRS ${GLIB_INCLUDE_DIR} ${GLIBCONFIG_INCLUDE_DIR}) # Version detection if (EXISTS "${GLIBCONFIG_INCLUDE_DIR}/glibconfig.h") file(READ "${GLIBCONFIG_INCLUDE_DIR}/glibconfig.h" GLIBCONFIG_H_CONTENTS) string(REGEX MATCH "#define GLIB_MAJOR_VERSION ([0-9]+)" _dummy "${GLIBCONFIG_H_CONTENTS}") set(GLIB_VERSION_MAJOR "${CMAKE_MATCH_1}") string(REGEX MATCH "#define GLIB_MINOR_VERSION ([0-9]+)" _dummy "${GLIBCONFIG_H_CONTENTS}") set(GLIB_VERSION_MINOR "${CMAKE_MATCH_1}") string(REGEX MATCH "#define GLIB_MICRO_VERSION ([0-9]+)" _dummy "${GLIBCONFIG_H_CONTENTS}") set(GLIB_VERSION_MICRO "${CMAKE_MATCH_1}") set(GLIB_VERSION "${GLIB_VERSION_MAJOR}.${GLIB_VERSION_MINOR}.${GLIB_VERSION_MICRO}") endif () # Additional Glib components. We only look for libraries, as not all of them # have corresponding headers and all headers are installed alongside the main # glib ones. foreach (_component ${GLIB_FIND_COMPONENTS}) if (${_component} STREQUAL "gio") find_library(GLIB_GIO_LIBRARIES NAMES gio-2.0 HINTS ${_GLIB_LIBRARY_DIR}) set(ADDITIONAL_REQUIRED_VARS ${ADDITIONAL_REQUIRED_VARS} GLIB_GIO_LIBRARIES) elseif (${_component} STREQUAL "gobject") find_library(GLIB_GOBJECT_LIBRARIES NAMES gobject-2.0 HINTS ${_GLIB_LIBRARY_DIR}) set(ADDITIONAL_REQUIRED_VARS ${ADDITIONAL_REQUIRED_VARS} GLIB_GOBJECT_LIBRARIES) elseif (${_component} STREQUAL "gmodule") find_library(GLIB_GMODULE_LIBRARIES NAMES gmodule-2.0 HINTS ${_GLIB_LIBRARY_DIR}) set(ADDITIONAL_REQUIRED_VARS ${ADDITIONAL_REQUIRED_VARS} GLIB_GMODULE_LIBRARIES) elseif (${_component} STREQUAL "gthread") find_library(GLIB_GTHREAD_LIBRARIES NAMES gthread-2.0 HINTS ${_GLIB_LIBRARY_DIR}) set(ADDITIONAL_REQUIRED_VARS ${ADDITIONAL_REQUIRED_VARS} GLIB_GTHREAD_LIBRARIES) elseif (${_component} STREQUAL "gio-unix") pkg_check_modules(GIO_UNIX gio-unix-2.0) find_path(GLIB_GIO_UNIX_INCLUDE_DIR NAMES gio/gunixconnection.h HINTS ${GIO_UNIX_INCLUDEDIR} PATH_SUFFIXES gio-unix-2.0) set(ADDITIONAL_REQUIRED_VARS ${ADDITIONAL_REQUIRED_VARS} GLIB_GIO_UNIX_INCLUDE_DIR) endif () endforeach () include(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(GLIB REQUIRED_VARS GLIB_INCLUDE_DIRS GLIB_LIBRARIES ${ADDITIONAL_REQUIRED_VARS} VERSION_VAR GLIB_VERSION) mark_as_advanced( GLIBCONFIG_INCLUDE_DIR GLIB_GIO_LIBRARIES GLIB_GIO_UNIX_INCLUDE_DIR GLIB_GMODULE_LIBRARIES GLIB_GOBJECT_LIBRARIES GLIB_GTHREAD_LIBRARIES GLIB_INCLUDE_DIR GLIB_INCLUDE_DIRS GLIB_LIBRARIES ) ukui-panel-3.0.6.4/cmake/ukui-build-tools/find-modules/FindXKBCommon.cmake0000644000175000017500000001022314203402514024623 0ustar fengfeng#.rst: # FindXKBCommon # ----------- # # Try to find XKBCommon. # # This is a component-based find module, which makes use of the COMPONENTS # and OPTIONAL_COMPONENTS arguments to find_module. The following components # are available:: # # XKBCommon X11 # # If no components are specified, this module will act as though all components # were passed to OPTIONAL_COMPONENTS. # # This module will define the following variables, independently of the # components searched for or found: # # ``XKBCommon_FOUND`` # TRUE if (the requested version of) XKBCommon is available # ``XKBCommon_VERSION`` # Found XKBCommon version # ``XKBCommon_TARGETS`` # A list of all targets imported by this module (note that there may be more # than the components that were requested) # ``XKBCommon_LIBRARIES`` # This can be passed to target_link_libraries() instead of the imported # targets # ``XKBCommon_INCLUDE_DIRS`` # This should be passed to target_include_directories() if the targets are # not used for linking # ``XKBCommon_DEFINITIONS`` # This should be passed to target_compile_options() if the targets are not # used for linking # # For each searched-for components, ``XKBCommon__FOUND`` will be set to # TRUE if the corresponding XKBCommon library was found, and FALSE otherwise. If # ``XKBCommon__FOUND`` is TRUE, the imported target # ``XKBCommon::`` will be defined. #============================================================================= # Copyright 2017 Luís Pereira # Copyright (c) 2019 Tianjin KYLIN Information Technology Co., Ltd. * # Documentation adapted from the KF5 FindWayland module. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # 1. Redistributions of source code must retain the copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # 3. The name of the author may not be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #============================================================================= include(ECMFindModuleHelpers) ecm_find_package_version_check(XKBCommon) set(XKBCommon_known_components XKBCommon X11) unset(XKBCommon_XKBCommon_component_deps) set(XKBCommon_XKBCommon_pkg_config "xkbcommon") set(XKBCommon_XKBCommon_lib "xkbcommon") set(XKBCommon_XKBCommon_header "xkbcommon/xkbcommon.h") set(XKBCommon_X11_component_deps XKBCommon) set(XKBCommon_X11_pkg_config "xkbcommon-x11") set(XKBCommon_X11_lib "xkbcommon-x11") set(XKBCommon_X11_header "xkbcommon/xkbcommon-x11.h") ecm_find_package_parse_components(XKBCommon RESULT_VAR XKBCommon_components KNOWN_COMPONENTS ${XKBCommon_known_components} ) ecm_find_package_handle_library_components(XKBCommon COMPONENTS ${XKBCommon_components} ) find_package_handle_standard_args(XKBCommon FOUND_VAR XKBCommon_FOUND REQUIRED_VARS XKBCommon_LIBRARIES XKBCommon_INCLUDE_DIRS VERSION_VAR XKBCommon_VERSION HANDLE_COMPONENTS ) include(FeatureSummary) set_package_properties(XKBCommon PROPERTIES URL "https://xkbcommon.org" DESCRIPTION "A library to handle keyboard descriptions" ) ukui-panel-3.0.6.4/cmake/ukui-build-tools/find-modules/FindXCB.cmake0000644000175000017500000000366514203402514023456 0ustar fengfeng#.rst: # FindXCB # ------- # # Find XCB libraries # # Tries to find xcb libraries on unix systems. # # - Be sure to set the COMPONENTS to the components you want to link to # - The XCB_LIBRARIES variable is set ONLY to your COMPONENTS list # - To use only a specific component check the XCB_LIBRARIES_${COMPONENT} variable # # The following values are defined # # :: # # XCB_FOUND - True if xcb is available # XCB_INCLUDE_DIRS - Include directories for xcb # XCB_LIBRARIES - List of libraries for xcb # XCB_DEFINITIONS - List of definitions for xcb # #============================================================================= # Copyright (c) 2015 Jari Vetoniemi # Copyright (c) 2019 Tianjin KYLIN Information Technology Co., Ltd. * # Distributed under the OSI-approved BSD License (the "License"); # # This software is distributed WITHOUT ANY WARRANTY; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # See the License for more information. #============================================================================= include(FeatureSummary) set_package_properties(XCB PROPERTIES URL "https://xcb.freedesktop.org/" DESCRIPTION "X protocol C-language Binding") find_package(PkgConfig) pkg_check_modules(PC_XCB xcb ${XCB_FIND_COMPONENTS}) find_library(XCB_LIBRARIES xcb HINTS ${PC_XCB_LIBRARY_DIRS}) find_path(XCB_INCLUDE_DIRS xcb/xcb.h PATH_SUFFIXES xcb HINTS ${PC_XCB_INCLUDE_DIRS}) foreach(COMPONENT ${XCB_FIND_COMPONENTS}) find_library(XCB_LIBRARIES_${COMPONENT} ${COMPONENT} HINTS ${PC_XCB_LIBRARY_DIRS}) list(APPEND XCB_LIBRARIES ${XCB_LIBRARIES_${COMPONENT}}) mark_as_advanced(XCB_LIBRARIES_${COMPONENT}) endforeach(COMPONENT ${XCB_FIND_COMPONENTS}) set(XCB_DEFINITIONS ${PC_XCB_CFLAGS_OTHER}) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(XCB DEFAULT_MSG XCB_LIBRARIES XCB_INCLUDE_DIRS) mark_as_advanced(XCB_INCLUDE_DIRS XCB_LIBRARIES XCB_DEFINITIONS) ukui-panel-3.0.6.4/cmake/ukui-build-tools/find-modules/FindMenuCache.cmake0000644000175000017500000000772214203402514024670 0ustar fengfeng# Copyright (c) 2010, Rafael Fernández López, # Copyright (c) 2016, Luís Pereira, # Copyright (c) 2019 Tianjin KYLIN Information Technology Co., Ltd. * # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # 3. Neither the name of the University nor the names of its contributors # may be used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. #.rst: # FindMenuCache # ----------- # # Try to find the MenuCache library # # Once done this will define # # :: # # MENUCACHE_FOUND - System has the MenuCache library # MENUCACHE_INCLUDE_DIR - The MenuCache library include directory # MENUCACHE_INCLUDE_DIRS - Location of the headers needed to use the MenuCache library # MENUCACHE_LIBRARIES - The libraries needed to the MenuCache library # MENUCACHE_DEFINITIONS - Compiler switches required for using the MenuCache library # MENUCACHE_VERSION_STRING - the version of MenuCache library found # use pkg-config to get the directories and then use these values # in the find_path() and find_library() calls find_package(PkgConfig) pkg_check_modules(PC_MENUCACHE libmenu-cache) set(MENUCACHE_DEFINITIONS ${PC_MENUCACHE_CFLAGS_OTHER}) find_path(MENUCACHE_INCLUDE_DIRS NAMES menu-cache.h menu-cache/menu-cache.h HINTS ${PC_MENUCACHE_INCLUDEDIR} ${PC_MENUCACHE_INCLUDE_DIRS} PATH_SUFFIXES libmenu-cache ) find_library(MENUCACHE_LIBRARIES NAMES menu-cache libmenu-cache HINTS ${PC_MENUCACHE_LIBDIR} ${PC_MENUCACHE_LIBRARY_DIRS} ) # iterate over all dependencies unset(FD_LIBRARIES) foreach(depend ${PC_MENUCACHE_LIBRARIES}) find_library(_DEPEND_LIBRARIES NAMES ${depend} HINTS ${PC_MENUCACHE_LIBDIR} ${PC_MENUCACHE_LIBRARY_DIRS} ) if (_DEPEND_LIBRARIES) list(APPEND FD_LIBRARIES ${_DEPEND_LIBRARIES}) endif() unset(_DEPEND_LIBRARIES CACHE) endforeach() set(MENUCACHE_VERSION_STRING ${PC_MENUCACHE_VERSION}) set(MENUCACHE_INCLUDE_DIR ${PC_MENUCACHE_INCLUDEDIR}) list(APPEND MENUCACHE_INCLUDE_DIRS ${MENUCACHE_INCLUDE_DIR} ${PC_MENUCACHE_INCLUDE_DIRS} ) list(REMOVE_DUPLICATES MENUCACHE_INCLUDE_DIRS) list(APPEND MENUCACHE_LIBRARIES ${FD_LIBRARIES} ) list(REMOVE_DUPLICATES MENUCACHE_LIBRARIES) # handle the QUIETLY and REQUIRED arguments and set MENUCACHE_FOUND to TRUE if # all listed variables are TRUE include(FindPackageHandleStandardArgs) find_package_handle_standard_args(MenuCache REQUIRED_VARS MENUCACHE_LIBRARIES MENUCACHE_INCLUDE_DIR MENUCACHE_INCLUDE_DIRS VERSION_VAR MENUCACHE_VERSION_STRING) mark_as_advanced(MENUCACHE_INCLUDE_DIR MENUCACHE_LIBRARIES) ukui-panel-3.0.6.4/cmake/ukui-build-tools/find-modules/FindUDev.cmake0000644000175000017500000000527314203402514023702 0ustar fengfeng# - Try to find the UDev library # Once done this will define # # UDEV_FOUND - system has UDev # UDEV_INCLUDE_DIR - the libudev include directory # UDEV_LIBS - The libudev libraries # Copyright (c) 2010, Rafael Fernández López, # Copyright (c) 2016, Luís Pereira, # Copyright (c) 2019 Tianjin KYLIN Information Technology Co., Ltd. * # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # 3. Neither the name of the University nor the names of its contributors # may be used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. find_package(PkgConfig) pkg_check_modules(PC_UDEV libudev) find_path(UDEV_INCLUDE_DIR libudev.h HINTS ${PC_UDEV_INCLUDEDIR} ${PC_UDEV_INCLUDE_DIRS}) find_library(UDEV_LIBS udev HINTS ${PC_UDEV_LIBDIR} ${PC_UDEV_LIBRARY_DIRS}) if(UDEV_INCLUDE_DIR AND UDEV_LIBS) include(CheckFunctionExists) include(CMakePushCheckState) cmake_push_check_state() set(CMAKE_REQUIRED_LIBRARIES ${UDEV_LIBS} ) cmake_pop_check_state() endif() set(UDEV_VERSION_STRING ${PC_UDEV_VERSION}) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(UDev REQUIRED_VARS UDEV_INCLUDE_DIR UDEV_LIBS VERSION_VAR ${UDEV_VERSION_STRING}) mark_as_advanced(UDEV_INCLUDE_DIR UDEV_LIBS) include(FeatureSummary) set_package_properties(UDev PROPERTIES URL "https://www.kernel.org/pub/linux/utils/kernel/hotplug/udev/udev.html" DESCRIPTION "Linux dynamic device management") ukui-panel-3.0.6.4/cmake/ukui-build-tools/find-modules/FindExif.cmake0000644000175000017500000000722314203402514023727 0ustar fengfeng# Copyright (c) 2010, Rafael Fernández López, # Copyright (c) 2016, Luís Pereira, # Copyright (c) 2019 Tianjin KYLIN Information Technology Co., Ltd. * # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # 3. Neither the name of the University nor the names of its contributors # may be used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. #.rst: # FindExif # ----------- # # Try to find the Exif library # # Once done this will define # # :: # # EXIF_FOUND - System has the Exif library # EXIF_INCLUDE_DIR - The Exif library include directory # EXIF_INCLUDE_DIRS - Location of the headers needed to use the Exif library # EXIF_LIBRARIES - The libraries needed to use the Exif library # EXIF_DEFINITIONS - Compiler switches required for using the Exif library # EXIF_VERSION_STRING - the version of the Exif library found # use pkg-config to get the directories and then use these values # in the find_path() and find_library() calls find_package(PkgConfig) pkg_check_modules(PC_EXIF libexif) set(EXIF_DEFINITIONS ${PC_EXIF_CFLAGS_OTHER}) find_path(EXIF_INCLUDE_DIR NAMES libexif/exif-data.h HINTS ${PC_EXIF_INCLUDEDIR} ${PC_EXIF_INCLUDE_DIRS} PATH_SUFFIXES libexif ) find_library(EXIF_LIBRARIES NAMES exif libexif HINTS ${PC_EXIF_LIBDIR} ${PC_EXIF_LIBRARY_DIRS} ) # iterate over all dependencies unset(FD_LIBRARIES) foreach(depend ${PC_EXIF_LIBRARIES}) find_library(_DEPEND_LIBRARIES NAMES ${depend} HINTS ${PC_EXIF_LIBDIR} ${PC_EXIF_LIBRARY_DIRS} ) if (_DEPEND_LIBRARIES) list(APPEND FD_LIBRARIES ${_DEPEND_LIBRARIES}) endif() unset(_DEPEND_LIBRARIES CACHE) endforeach() set(EXIF_VERSION_STRING ${PC_EXIF_VERSION}) set(EXIF_INCLUDE_DIR ${PC_EXIF_INCLUDEDIR}) list(APPEND EXIF_INCLUDE_DIRS ${EXIF_INCLUDE_DIR} ${PC_EXIF_INCLUDE_DIRS} ) list(REMOVE_DUPLICATES EXIF_INCLUDE_DIRS) list(APPEND EXIF_LIBRARIES ${FD_LIBRARIES} ) list(REMOVE_DUPLICATES EXIF_LIBRARIES) # handle the QUIETLY and REQUIRED arguments and set EXIF_FOUND to TRUE if # all listed variables are TRUE include(FindPackageHandleStandardArgs) find_package_handle_standard_args(Exif REQUIRED_VARS EXIF_LIBRARIES EXIF_INCLUDE_DIR EXIF_INCLUDE_DIRS VERSION_VAR EXIF_VERSION_STRING) mark_as_advanced(EXIF_INCLUDE_DIR EXIF_LIBRARIES) ukui-panel-3.0.6.4/cmake/UkuiPluginTranslationTs.cmake0000644000175000017500000000376414203402514021265 0ustar fengfengmacro(ukui_plugin_translate_ts PLUGIN) set(TS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/translation/${PLUGIN}_zh_CN.ts) set(B_QM_FILES ${CMAKE_CURRENT_BINARY_DIR}/translation/) if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/translation/) else() execute_process( COMMAND mkdir ${CMAKE_CURRENT_SOURCE_DIR}/translation/ ) endif() if(EXISTS ${TS_FILES}) message(STATUS "${TS_FILES} is EXISTS") execute_process( COMMAND lupdate -recursive ${CMAKE_CURRENT_SOURCE_DIR} -target-language zh_CN -ts ${TS_FILES} ) execute_process( COMMAND lrelease ${TS_FILES} ) else() execute_process( COMMAND lupdate -recursive ${CMAKE_CURRENT_SOURCE_DIR} -target-language zh_CN -ts ${TS_FILES} ) execute_process( COMMAND lrelease ${TS_FILES} ) endif() if(EXISTS ${B_QM_FILES}) message(STATUS "${PLUGIN} buildQM dir is EXISTS") else() message(STATUS "${PLUGIN} buildQM dir is not EXISTS") execute_process( COMMAND mkdir ${B_QM_FILES} ) message(STATUS "${PLUGIN} buildQM dir is created") endif() set(P_QM_FILES ${CMAKE_CURRENT_SOURCE_DIR}/translation/${PLUGIN}_zh_CN.qm) if(EXISTS ${P_QM_FILES}) message(STATUS "${PLUGIN} proQM file is EXISTS") execute_process( COMMAND cp -f ${P_QM_FILES} ${B_QM_FILES} ) execute_process( COMMAND rm -f ${P_QM_FILES} ) message(STATUS "${PLUGIN} buildQM file is created") else() message(STATUS "${PLUGIN} buildQM file is not EXISTS") endif() if(${PLUGIN} STREQUAL "panel") set(P_QM_INSTALL ${PACKAGE_DATA_DIR}/${PLUGIN}/translation) message(STATUS " panel translation install : ${P_QM_INSTALL}") else() set(P_QM_INSTALL ${PACKAGE_DATA_DIR}/plugin-${PLUGIN}/translation) message(STATUS " plugin ${PLUGIN} translation install : ${P_QM_INSTALL}") endif() install(DIRECTORY ${B_QM_FILES} DESTINATION ${P_QM_INSTALL}) ADD_DEFINITIONS(-DQM_INSTALL=\"${P_QM_INSTALL}/${PLUGIN}_zh_CN.qm\") ADD_DEFINITIONS(-DPLUGINNAME=\"${PLUGIN}\") endmacro() ukui-panel-3.0.6.4/panel-daemon/0000755000175000017500000000000014203402514014707 5ustar fengfengukui-panel-3.0.6.4/panel-daemon/filewatcher/0000755000175000017500000000000014203402514017204 5ustar fengfengukui-panel-3.0.6.4/panel-daemon/filewatcher/filewatcher.cpp0000644000175000017500000000722714203402514022215 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include #define APPLICATION_PATH "/usr/share/applications/" FileWatcher::FileWatcher() { fsWatcher=new QFileSystemWatcher(this); fsWatcher->addPath(APPLICATION_PATH); initDirMonitor(APPLICATION_PATH); connect(fsWatcher,&QFileSystemWatcher::directoryChanged,[this](){ directoryUpdated(APPLICATION_PATH); }); qDebug()<<"********************"; } void FileWatcher::initDirMonitor(QString path) { const QDir dir(path); m_currentContentsMap[path] = dir.entryList(QDir::NoDotAndDotDot | QDir::AllDirs | QDir::Files, QDir::DirsFirst); } //只要任何监控的目录更新(添加、删除、重命名),就会调用。 void FileWatcher::directoryUpdated(const QString &path) { qDebug()<<"********************** "< newDirSet = QSet::fromList(newEntryList); QSet currentDirSet = QSet::fromList(currEntryList); // 添加了文件 QSet newFiles = newDirSet - currentDirSet; QStringList newFile = newFiles.toList(); // 文件已被移除 QSet deletedFiles = currentDirSet - newDirSet; QStringList deleteFile = deletedFiles.toList(); // 更新当前设置 m_currentContentsMap[path] = newEntryList; if (!newFile.isEmpty() && !deleteFile.isEmpty()) { // 文件/目录重命名 if ((newFile.count() == 1) && (deleteFile.count() == 1)) { // qDebug() << QString("File Renamed from %1 to %2").arg(deleteFile.first()).arg(newFile.first()); } } else { // 添加新文件/目录至Dir if (!newFile.isEmpty()) { // foreach (QString file, newFile) // { // // 处理操作每个新文件.... // } } // 从Dir中删除文件/目录 if (!deleteFile.isEmpty()) { // qDebug()<<"***************"< args; args.append(path+deleteFile.at(0)); qDebug()< #include #include #include #include class FileWatcher : public QObject { Q_OBJECT public: FileWatcher(); QFileSystemWatcher *fsWatcher; void initDirMonitor(QString path); QMap m_currentContentsMap; // 当前每个监控的内容目录列表 void directoryUpdated(const QString &path); signals: void DesktopDeleteFile(const QString &path, QStringList deleteFile); }; #endif // FILEWACTHER_H ukui-panel-3.0.6.4/panel-daemon/watchermanager.cpp0000644000175000017500000000407414203402514020410 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see WatcherManager::WatcherManager(QObject *parent) : QObject(parent) { register_dbus(); } WatcherManager::~WatcherManager() { delete taskbar_dbus; } void WatcherManager::register_dbus() { Server* dbus=new Server; connect(dbus,&Server::DesktopFileDelete, this,[=](){ qDebug()<<"signal send success!"; }); new DaemonAdaptor(dbus); QDBusConnection con=QDBusConnection::sessionBus(); if(!con.registerService("org.ukui.panel.daemon")) { qDebug()<<"error1:"< class DateWatcher : public QObject { Q_OBJECT public: explicit DateWatcher(QObject *parent = nullptr); }; #endif // DATEWATCHER_H ukui-panel-3.0.6.4/panel-daemon/datewather/datewatcher.cpp0000644000175000017500000000146014203402514022037 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include //file #include "filewatcher/filewatcher.h" #include "convert-desktop-windowid/convertdesktoptowinid.h" class Server : public QObject { Q_OBJECT Q_CLASSINFO("D-Bus Interface","org.ukui.panel.daemon") public: explicit Server(QObject *parent = 0); public Q_SLOTS: //desktop 文件路径转换为wid int DesktopToWID(QString desktop); //window Id 转化为desktop文件 QString WIDToDesktop(int id); void DesktopFileDeleteSlot(QString path,QStringList deleteFile); Q_SIGNALS: //desktop文件被删除 QString DesktopFileDelete(QString); // //时间改变 // QString TimeChanged(); private: FileWatcher *mFileWatcher; ConvertDesktopToWinId *mDesktop; }; #endif // UKUIPANEL_INFORMATION_H ukui-panel-3.0.6.4/panel-daemon/dbus-server/org.ukui.panel.daemon.xml0000644000175000017500000000120614203402514023774 0ustar fengfeng ukui-panel-3.0.6.4/panel-daemon/dbus-server/Readme.md0000644000175000017500000000201514203402514020665 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include "convert-desktop-windowid/convertdesktoptowinid.h" Server::Server(QObject *parent) : QObject(parent) { mFileWatcher = new FileWatcher(); connect(mFileWatcher,&FileWatcher::DesktopDeleteFile,this,&Server::DesktopFileDeleteSlot); mDesktop = new ConvertDesktopToWinId(); } QString Server::WIDToDesktop(int id) { return mDesktop->tranIdToDesktop(id); } int Server::DesktopToWID(QString desktop) { } void Server::DesktopFileDeleteSlot(QString path,QStringList deleteFile){ // emit DesktopFileDelete(path,deleteFile); } //QString Server::TimeChanged() //{ //} ukui-panel-3.0.6.4/panel-daemon/dbus-server/dbus-adaptor.h0000644000175000017500000000337414203402514021715 0ustar fengfeng/* * This file was generated by qdbusxml2cpp version 0.8 * Command line was: qdbusxml2cpp org.ukui.panel.daemon.xml -i server.h -a dbus-adaptor * * qdbusxml2cpp is Copyright (C) 2020 The Qt Company Ltd. * * This is an auto-generated file. * This file may have been hand-edited. Look for HAND-EDIT comments * before re-generating it. */ #ifndef DBUS-ADAPTOR_H #define DBUS-ADAPTOR_H #include #include #include "server.h" QT_BEGIN_NAMESPACE class QByteArray; template class QList; template class QMap; class QString; class QStringList; class QVariant; QT_END_NAMESPACE /* * Adaptor class for interface org.ukui.panel.daemon */ class DaemonAdaptor: public QDBusAbstractAdaptor { Q_OBJECT Q_CLASSINFO("D-Bus Interface", "org.ukui.panel.daemon") Q_CLASSINFO("D-Bus Introspection", "" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" "") public: DaemonAdaptor(QObject *parent); virtual ~DaemonAdaptor(); public: // PROPERTIES public Q_SLOTS: // METHODS void DesktopFileDeleteSlot(const QString &path, const QStringList &deleteFile); int DesktopToWID(const QString &desktop); QString WIDToDesktop(int id); Q_SIGNALS: // SIGNALS }; #endif ukui-panel-3.0.6.4/panel-daemon/dbus-server/dbus-adaptor.cpp0000644000175000017500000000303314203402514022240 0ustar fengfeng/* * This file was generated by qdbusxml2cpp version 0.8 * Command line was: qdbusxml2cpp org.ukui.panel.daemon.xml -i server.h -a dbus-adaptor * * qdbusxml2cpp is Copyright (C) 2020 The Qt Company Ltd. * * This is an auto-generated file. * Do not edit! All changes made to it will be lost. */ #include "dbus-adaptor.h" #include #include #include #include #include #include #include /* * Implementation of adaptor class DaemonAdaptor */ DaemonAdaptor::DaemonAdaptor(QObject *parent) : QDBusAbstractAdaptor(parent) { // constructor setAutoRelaySignals(true); } DaemonAdaptor::~DaemonAdaptor() { // destructor } void DaemonAdaptor::DesktopFileDeleteSlot(const QString &path, const QStringList &deleteFile) { // handle method call org.ukui.panel.daemon.DesktopFileDeleteSlot QMetaObject::invokeMethod(parent(), "DesktopFileDeleteSlot", Q_ARG(QString, path), Q_ARG(QStringList, deleteFile)); } int DaemonAdaptor::DesktopToWID(const QString &desktop) { // handle method call org.ukui.panel.daemon.DesktopToWID int out0; QMetaObject::invokeMethod(parent(), "DesktopToWID", Q_RETURN_ARG(int, out0), Q_ARG(QString, desktop)); return out0; } QString DaemonAdaptor::WIDToDesktop(int id) { // handle method call org.ukui.panel.daemon.WIDToDesktop QString out0; QMetaObject::invokeMethod(parent(), "WIDToDesktop", Q_RETURN_ARG(QString, out0), Q_ARG(int, id)); return out0; } ukui-panel-3.0.6.4/panel-daemon/watchermanager.h0000644000175000017500000000232014203402514020045 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include "filewatcher/filewatcher.h" #include "dbus-server/server.h" #include "dbus-server/dbus-adaptor.h" #include "pin-totaskbar/pintotaskbar.h" #include "pin-totaskbar/taskbar-dbus-adaptor.h" class WatcherManager : public QObject { Q_OBJECT public: explicit WatcherManager(QObject *parent = nullptr); ~WatcherManager(); private: void register_dbus(); PinToTaskbar* taskbar_dbus; }; #endif // WATCHERMANAGER_H ukui-panel-3.0.6.4/panel-daemon/jsonwathcer/0000755000175000017500000000000014203402514017236 5ustar fengfengukui-panel-3.0.6.4/panel-daemon/jsonwathcer/jsonwacther.cpp0000644000175000017500000000142014203402514022266 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see class JsonWacther { public: JsonWacther(); }; #endif // JSONWACTHER_H ukui-panel-3.0.6.4/panel-daemon/pin-totaskbar/0000755000175000017500000000000014203402514017465 5ustar fengfengukui-panel-3.0.6.4/panel-daemon/pin-totaskbar/org.ukui.panel.xml0000644000175000017500000000116114203402514023047 0ustar fengfeng ukui-panel-3.0.6.4/panel-daemon/pin-totaskbar/Readme.md0000644000175000017500000000202314203402514021201 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include "pintotaskbar.h" QT_BEGIN_NAMESPACE class QByteArray; template class QList; template class QMap; class QString; class QStringList; class QVariant; QT_END_NAMESPACE /* * Adaptor class for interface org.ukui.panel */ class PanelAdaptor: public QDBusAbstractAdaptor { Q_OBJECT Q_CLASSINFO("D-Bus Interface", "org.ukui.panel") Q_CLASSINFO("D-Bus Introspection", "" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" "") public: PanelAdaptor(QObject *parent); virtual ~PanelAdaptor(); public: // PROPERTIES public Q_SLOTS: // METHODS bool AddToTaskbar(const QString &desktop); bool CheckIfExist(const QString &desktop); bool RemoceFromTaskbar(const QString &desktop); Q_SIGNALS: // SIGNALS }; #endif ukui-panel-3.0.6.4/panel-daemon/pin-totaskbar/taskbar-dbus-adaptor.h0000644000175000017500000000333714203402514023656 0ustar fengfeng/* * This file was generated by qdbusxml2cpp version 0.8 * Command line was: qdbusxml2cpp org.ukui.panel.xml -i pintotaskbar.h -a taskbar-dbus-adaptor * * qdbusxml2cpp is Copyright (C) 2020 The Qt Company Ltd. * * This is an auto-generated file. * This file may have been hand-edited. Look for HAND-EDIT comments * before re-generating it. */ #ifndef TASKBAR-DBUS-ADAPTOR_H #define TASKBAR-DBUS-ADAPTOR_H #include #include #include "pintotaskbar.h" QT_BEGIN_NAMESPACE class QByteArray; template class QList; template class QMap; class QString; class QStringList; class QVariant; QT_END_NAMESPACE /* * Adaptor class for interface org.ukui.panel */ class PanelAdaptor: public QDBusAbstractAdaptor { Q_OBJECT Q_CLASSINFO("D-Bus Interface", "org.ukui.panel") Q_CLASSINFO("D-Bus Introspection", "" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" "") public: PanelAdaptor(QObject *parent); virtual ~PanelAdaptor(); public: // PROPERTIES public Q_SLOTS: // METHODS bool AddToTaskbar(const QString &desktop); bool CheckIfExist(const QString &desktop); bool RemoveFromTaskbar(const QString &desktop); Q_SIGNALS: // SIGNALS }; #endif ukui-panel-3.0.6.4/panel-daemon/pin-totaskbar/pintotaskbar.h0000644000175000017500000000227414203402514022344 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see class PinToTaskbar : public QObject { Q_OBJECT Q_CLASSINFO("D-Bus Interface","com.ukui.panel.desktop") public: PinToTaskbar(QObject *parent = 0); public Q_SLOTS: bool AddToTaskbar(const QString &desktop); bool RemoveFromTaskbar(const QString &desktop); bool CheckIfExist(const QString &desktop); private: QList > getTaskbarFixedList(); }; #endif // PINTOTASKBAR_H ukui-panel-3.0.6.4/panel-daemon/pin-totaskbar/dbus-adaptor.cpp0000644000175000017500000000300514203402514022554 0ustar fengfeng/* * This file was generated by qdbusxml2cpp version 0.8 * Command line was: qdbusxml2cpp org.ukui.panel.xml -i pintotaskbar.h -a dbus-adaptor * * qdbusxml2cpp is Copyright (C) 2020 The Qt Company Ltd. * * This is an auto-generated file. * Do not edit! All changes made to it will be lost. */ #include "dbus-adaptor.h" #include #include #include #include #include #include #include /* * Implementation of adaptor class PanelAdaptor */ PanelAdaptor::PanelAdaptor(QObject *parent) : QDBusAbstractAdaptor(parent) { // constructor setAutoRelaySignals(true); } PanelAdaptor::~PanelAdaptor() { // destructor } bool PanelAdaptor::AddToTaskbar(const QString &desktop) { // handle method call org.ukui.panel.AddToTaskbar bool out0; QMetaObject::invokeMethod(parent(), "AddToTaskbar", Q_RETURN_ARG(bool, out0), Q_ARG(QString, desktop)); return out0; } bool PanelAdaptor::CheckIfExist(const QString &desktop) { // handle method call org.ukui.panel.CheckIfExist bool out0; QMetaObject::invokeMethod(parent(), "CheckIfExist", Q_RETURN_ARG(bool, out0), Q_ARG(QString, desktop)); return out0; } bool PanelAdaptor::RemoceFromTaskbar(const QString &desktop) { // handle method call org.ukui.panel.RemoceFromTaskbar bool out0; QMetaObject::invokeMethod(parent(), "RemoceFromTaskbar", Q_RETURN_ARG(bool, out0), Q_ARG(QString, desktop)); return out0; } ukui-panel-3.0.6.4/panel-daemon/pin-totaskbar/taskbar-dbus-adaptor.cpp0000644000175000017500000000302514203402514024203 0ustar fengfeng/* * This file was generated by qdbusxml2cpp version 0.8 * Command line was: qdbusxml2cpp org.ukui.panel.xml -i pintotaskbar.h -a taskbar-dbus-adaptor * * qdbusxml2cpp is Copyright (C) 2020 The Qt Company Ltd. * * This is an auto-generated file. * Do not edit! All changes made to it will be lost. */ #include "taskbar-dbus-adaptor.h" #include #include #include #include #include #include #include /* * Implementation of adaptor class PanelAdaptor */ PanelAdaptor::PanelAdaptor(QObject *parent) : QDBusAbstractAdaptor(parent) { // constructor setAutoRelaySignals(true); } PanelAdaptor::~PanelAdaptor() { // destructor } bool PanelAdaptor::AddToTaskbar(const QString &desktop) { // handle method call org.ukui.panel.AddToTaskbar bool out0; QMetaObject::invokeMethod(parent(), "AddToTaskbar", Q_RETURN_ARG(bool, out0), Q_ARG(QString, desktop)); return out0; } bool PanelAdaptor::CheckIfExist(const QString &desktop) { // handle method call org.ukui.panel.CheckIfExist bool out0; QMetaObject::invokeMethod(parent(), "CheckIfExist", Q_RETURN_ARG(bool, out0), Q_ARG(QString, desktop)); return out0; } bool PanelAdaptor::RemoveFromTaskbar(const QString &desktop) { // handle method call org.ukui.panel.RemoveFromTaskbar bool out0; QMetaObject::invokeMethod(parent(), "RemoveFromTaskbar", Q_RETURN_ARG(bool, out0), Q_ARG(QString, desktop)); return out0; } ukui-panel-3.0.6.4/panel-daemon/pin-totaskbar/pintotaskbar.cpp0000644000175000017500000000442014203402514022672 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see PinToTaskbar::PinToTaskbar(QObject *parent) : QObject(parent) { } bool PinToTaskbar::AddToTaskbar(const QString &desktop) { QDBusMessage message = QDBusMessage::createSignal("/taskbar/quicklaunch", "org.ukui.panel.taskbar", "AddToTaskbar"); message << desktop; QDBusConnection::sessionBus().send(message); return true; } bool PinToTaskbar::RemoveFromTaskbar(const QString &desktop) { QDBusMessage message = QDBusMessage::createSignal("/taskbar/quicklaunch", "org.ukui.panel.taskbar", "RemoveFromTaskbar"); message << desktop; QDBusConnection::sessionBus().send(message); return true; } bool PinToTaskbar::CheckIfExist(const QString &desktop) { QString fixdDesktop; const auto apps = getTaskbarFixedList(); for (const QMap &app : apps) { fixdDesktop = app.value("desktop", "").toString(); if (fixdDesktop.contains(desktop)) { return true; } } return false; } QList > PinToTaskbar::getTaskbarFixedList() { QSettings settings(QDir::homePath() + "/.config/ukui/panel.conf", QSettings::IniFormat); QList > array; int size = settings.beginReadArray("/taskbar/apps"); for (int i = 0; i < size; ++i) { settings.setArrayIndex(i); QMap hash; const auto keys = settings.childKeys(); for (const QString &key : keys) { hash[key] = settings.value(key); } array << hash; } return array; } ukui-panel-3.0.6.4/panel-daemon/resources/0000755000175000017500000000000014203402514016721 5ustar fengfengukui-panel-3.0.6.4/panel-daemon/resources/ukui-panel-daemon.desktop0000644000175000017500000000021014203402514023620 0ustar fengfeng[Desktop Entry] Name=Panel Daemon Comment=ukui panel daemon Exec=panel-daemon Type=Application OnlyShowIn=UKUI; X-UKUI-AutoRestart=true ukui-panel-3.0.6.4/panel-daemon/CMakeLists.txt0000644000175000017500000000344214203402514017452 0ustar fengfengcmake_minimum_required(VERSION 3.1.0) project(panel-daemon) #判断编译器类型,如果是gcc编译器,则在编译选项中加入c++11支持 if(CMAKE_COMPILER_IS_GNUCXX) set(CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}") message(STATUS "optional:-std=c++11") endif(CMAKE_COMPILER_IS_GNUCXX) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) set(CMAKE_AUTOUIC ON) if(CMAKE_VERSION VERSION_LESS "3.7.0") set(CMAKE_INCLUDE_CURRENT_DIR ON) endif() find_package(Qt5 COMPONENTS Widgets Network REQUIRED) find_package(Qt5DBus REQUIRED) find_package(PkgConfig REQUIRED) find_package(KF5WindowSystem REQUIRED) pkg_check_modules(GLIB2 REQUIRED glib-2.0 gio-2.0 udisks2) pkg_check_modules(QGS REQUIRED gsettings-qt) include_directories(${GLIB2_INCLUDE_DIRS}) include_directories(${QGS_INCLUDE_DIRS}) add_executable(panel-daemon jsonwathcer/jsonwacther.cpp jsonwathcer/jsonwacther.h filewatcher/filewatcher.cpp filewatcher/filewatcher.h convert-desktop-windowid/convertdesktoptowinid.cpp convert-desktop-windowid/convertdesktoptowinid.h pin-totaskbar/pintotaskbar.cpp pin-totaskbar/pintotaskbar.h pin-totaskbar/taskbar-dbus-adaptor.cpp pin-totaskbar/taskbar-dbus-adaptor.h dbus-server/server.cpp dbus-server/server.h dbus-server/dbus-adaptor.cpp dbus-server/dbus-adaptor.h datewather/datewatcher.cpp datewather/datewatcher.h watchermanager.cpp watchermanager.h main.cpp ) add_definitions(-DQT_MESSAGELOGCONTEXT) target_link_libraries(${PROJECT_NAME} Qt5::Widgets Qt5::DBus Qt5::Network ${GLIB2_LIBRARIES} ${QGS_LIBRARIES} KF5::WindowSystem) install(TARGETS panel-daemon DESTINATION bin) install(FILES resources/ukui-panel-daemon.desktop DESTINATION "/etc/xdg/autostart/" COMPONENT Runtime ) ukui-panel-3.0.6.4/panel-daemon/convert-desktop-windowid/0000755000175000017500000000000014203402514021660 5ustar fengfengukui-panel-3.0.6.4/panel-daemon/convert-desktop-windowid/convertdesktoptowinid.cpp0000644000175000017500000002533414203402514027043 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include ConvertDesktopToWinId::ConvertDesktopToWinId() { //connect(KWindowSystem::self(), &KWindowSystem::windowAdded, this, &ConvertDesktopToWinId::tranIdToDesktop); } QString ConvertDesktopToWinId::tranIdToDesktop(WId id) { QString desktopName = confirmDesktopFile(id); qDebug() << "desktopName is :" << desktopName; return desktopName; } QString ConvertDesktopToWinId::confirmDesktopFile(WId id) { KWindowInfo info(id, 0, NET::WM2AllProperties); m_desktopfilePath = ""; m_dir = new QDir(DEKSTOP_FILE_PATH); m_list = m_dir->entryInfoList(); //跳过 ./ 和 ../ 目录 m_list.removeAll(QFile(USR_SHARE_APP_CURRENT)); m_list.removeAll(QFile(USR_SHARE_APP_UPER)); //加入自启动目录下的desktop文件,优先使用/usr/share/applications/下的desktop QDir dir(AUTOSTART_DEKSTOP_FILE_PATH); QFileInfoList autostartList = dir.entryInfoList(); m_list.append(autostartList); //第一种方法:比较名字一致性 if (m_desktopfilePath.isEmpty()) { m_classClass = info.windowClassClass().toLower(); m_className = info.windowClassName(); //匹配安卓兼容 if (m_className == "kylin-kmre-window") { searchAndroidApp(info); return m_desktopfilePath; } //匹配Inter端腾讯教育 if (m_className == "txeduplatform") { searchTXeduApp(id); return m_desktopfilePath; } QFile file(QString("/proc/%1/status").arg(info.pid())); if (file.open(QIODevice::ReadOnly)) { char buf[1024]; qint64 len=file.readLine(buf,sizeof(buf)); if (len!=-1) { m_statusName = QString::fromLocal8Bit(buf).remove("Name:").remove("\t").remove("\n"); } } compareClassName(); } //第二种方法:获取点击应用时大部分desktop文件名 if (m_desktopfilePath.isEmpty()) { searchFromEnviron(info); } //第三种方法:比较cmd命令行操作一致性 if (m_desktopfilePath.isEmpty()) { QFile file(QString("/proc/%1/cmdline").arg(info.pid())); if (file.open(QIODevice::ReadOnly)) { char buf[1024]; qint64 len=file.readLine(buf,sizeof(buf)); if (len!=-1) { m_cmdLine = QString::fromLocal8Bit(buf).remove("\n"); } } compareCmdExec(); } //第四种方法:匹配部分字段 if (m_desktopfilePath.isEmpty()) { compareLastStrategy(); } return m_desktopfilePath; } void ConvertDesktopToWinId::searchAndroidApp(KWindowInfo info) { m_androidDir = new QDir(QString(QDir::homePath() + ANDROID_FILE_PATH)); m_androidList = m_androidDir->entryInfoList(); m_androidList.removeAll(QDir::homePath() + ANDROID_APP_CURRENT); m_androidList.removeAll(QDir::homePath() + ANDROID_APP_UPER); QFile file(QString("/proc/%1/cmdline").arg(info.pid())); file.open(QIODevice::ReadOnly); QByteArray cmd = file.readAll(); file.close(); QList cmdList = cmd.split('\0'); for(int i = 0; i < m_androidList.size(); i++){ QFileInfo fileInfo = m_androidList.at(i); QString desktopName = fileInfo.filePath(); if(!fileInfo.filePath().endsWith(".desktop")){ continue; } desktopName = desktopName.mid(desktopName.lastIndexOf("/") + 1); desktopName = desktopName.left(desktopName.lastIndexOf(".")); if(desktopName == cmdList.at(10)){ m_desktopfilePath = fileInfo.filePath(); break; } } } void ConvertDesktopToWinId::searchTXeduApp(WId id) { KWindowInfo info(id, NET::WMAllProperties); QString name = info.name(); for (int i = 0; i < m_list.size(); i++) { QString cmd; QFileInfo fileInfo = m_list.at(i); if (!fileInfo.filePath().endsWith(".desktop")) { continue; } cmd.sprintf(GET_DESKTOP_NAME_MAIN, fileInfo.filePath().toStdString().data()); QString desktopName = getDesktopFileName(cmd).remove("\n"); if (desktopName == name) { m_desktopfilePath = fileInfo.filePath(); break; } } } void ConvertDesktopToWinId::searchFromEnviron(KWindowInfo info) { QFile file("/proc/" + QString::number(info.pid()) + "/environ"); file.open(QIODevice::ReadOnly); QByteArray BA = file.readAll(); file.close(); QList list_BA = BA.split('\0'); for (int i = 0; i < list_BA.length(); i++) { if (list_BA.at(i).startsWith("GIO_LAUNCHED_DESKTOP_FILE=")) { m_desktopfilePath = list_BA.at(i); m_desktopfilePath = m_desktopfilePath.mid(m_desktopfilePath.indexOf("=") + 1); //desktop文件地址需要重写 m_desktopfilePath = m_desktopfilePath.mid(m_desktopfilePath.lastIndexOf("/") + 1); break; } } //desktop文件地址重写 if (!m_desktopfilePath.isEmpty()) { for (int i = 0; i < m_list.size(); i++) { QFileInfo fileInfo = m_list.at(i);; if (fileInfo.filePath() == DEKSTOP_FILE_PATH + m_desktopfilePath) { m_desktopfilePath = fileInfo.filePath(); break; } } } } void ConvertDesktopToWinId::compareClassName() { for (int i = 0; i < m_list.size(); i++) { QFileInfo fileInfo = m_list.at(i);; QString path_desktop_name = fileInfo.filePath(); if (!fileInfo.filePath().endsWith(".desktop")) { continue; } path_desktop_name = path_desktop_name.mid(path_desktop_name.lastIndexOf("/") + 1); path_desktop_name = path_desktop_name.left(path_desktop_name.lastIndexOf(".")); if (path_desktop_name == m_classClass || path_desktop_name == m_className || path_desktop_name == m_statusName) { m_desktopfilePath = fileInfo.filePath(); break; } } } void ConvertDesktopToWinId::compareCmdExec() { for (int i = 0; i < m_list.size(); i++) { QString cmd; QFileInfo fileInfo = m_list.at(i); if (!fileInfo.filePath().endsWith(".desktop")) { continue; } cmd.sprintf(GET_DESKTOP_EXEC_NAME_MAIN, fileInfo.filePath().toStdString().data()); QString desktopFileExeName = getDesktopFileName(cmd).remove("\n"); if (desktopFileExeName.isEmpty()) { continue; } if (desktopFileExeName == m_cmdLine || desktopFileExeName.startsWith(m_cmdLine) || m_cmdLine.startsWith(desktopFileExeName)) { m_desktopfilePath = fileInfo.filePath(); break; } //仅仅是为了适配微信 if (m_desktopfilePath.isEmpty()) { desktopFileExeName = "/usr/lib/" + desktopFileExeName; if (desktopFileExeName == m_cmdLine || desktopFileExeName.startsWith(m_cmdLine) || m_cmdLine.startsWith(desktopFileExeName)) { m_desktopfilePath = fileInfo.filePath(); } } } } //最后的匹配策略汇总 void ConvertDesktopToWinId::compareLastStrategy() { compareCmdName(); if (m_desktopfilePath.isEmpty()) { compareDesktopClass(); } if (m_desktopfilePath.isEmpty()) { containsName(); } } void ConvertDesktopToWinId::compareCmdName() { for (int i = 0; i < m_list.size(); i++) { QString cmd; QFileInfo fileInfo = m_list.at(i); if (!fileInfo.filePath().endsWith(".desktop")) { continue; } cmd.sprintf(GET_DESKTOP_EXEC_NAME_MAIN, fileInfo.filePath().toStdString().data()); QString desktopFileExeName = getDesktopFileName(cmd).remove("\n"); if (desktopFileExeName.isEmpty()) { continue; } if (desktopFileExeName.startsWith(m_className) || desktopFileExeName.endsWith(m_className)) { m_desktopfilePath = fileInfo.filePath(); break; } } } void ConvertDesktopToWinId::compareDesktopClass() { for (int i = 0; i < m_list.size(); i++) { QFileInfo fileInfo = m_list.at(i); QString path_desktop_name = fileInfo.filePath(); if (!fileInfo.filePath().endsWith(".desktop")) { continue; } path_desktop_name = path_desktop_name.mid(path_desktop_name.lastIndexOf("/") + 1); path_desktop_name = path_desktop_name.left(path_desktop_name.lastIndexOf(".")); if (path_desktop_name.startsWith(m_className) || path_desktop_name.endsWith(m_className)) { m_desktopfilePath = fileInfo.filePath(); break; } else if (m_className.startsWith(path_desktop_name) || m_className.endsWith(path_desktop_name)) { m_desktopfilePath = fileInfo.filePath(); break; } } } void ConvertDesktopToWinId::containsName() { for (int i = 0; i < m_list.size(); i++) { QString cmd; QFileInfo fileInfo = m_list.at(i); QString path_desktop_name = fileInfo.filePath(); if (!fileInfo.filePath().endsWith(".desktop")) { continue; } cmd.sprintf(GET_DESKTOP_EXEC_NAME_MAIN, fileInfo.filePath().toStdString().data()); QString desktopFileExeName = getDesktopFileName(cmd).remove("\n"); path_desktop_name = path_desktop_name.mid(path_desktop_name.lastIndexOf("/") + 1); path_desktop_name = path_desktop_name.left(path_desktop_name.lastIndexOf(".")); if (path_desktop_name.contains(m_className) || desktopFileExeName.contains(m_className)) { m_desktopfilePath = fileInfo.filePath(); break; } } } //执行头文件中宏定义写好的终端指令获取对应的Exec字段 QString ConvertDesktopToWinId::getDesktopFileName(QString cmd) { char name[200]; FILE *fp1 = NULL; if ((fp1 = popen(cmd.toStdString().data(), "r")) == NULL) return QString(); memset(name, 0, sizeof(name)); fgets(name, sizeof(name), fp1); pclose(fp1); return QString(name); } ConvertDesktopToWinId::~ConvertDesktopToWinId() { } ukui-panel-3.0.6.4/panel-daemon/convert-desktop-windowid/convertdesktoptowinid.h0000644000175000017500000000576614203402514026517 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #define AUTOSTART_DEKSTOP_FILE_PATH "/etc/xdg/autostart/" #define DEKSTOP_FILE_PATH "/usr/share/applications/" #define USR_SHARE_APP_CURRENT "/usr/share/applications/." #define USR_SHARE_APP_UPER "/usr/share/applications/.." #define PEONY_TRASH "/usr/share/applications/peony-trash.desktop" #define PEONY_COMUTER "/usr/share/applications/peony-computer.desktop" #define PEONY_HOME "/usr/share/applications/peony-home.desktop" #define PEONY_MAIN "/usr/share/applications/peony.desktop" #define GET_DESKTOP_EXEC_NAME_MAIN "cat %s | awk '{if($1~\"Exec=\")if($2~\"\%\"){print $1} else print}' | cut -d '=' -f 2" #define GET_DESKTOP_NAME_MAIN "cat %s | awk '{if($1~\"Name=\")if($2~\"\%\"){print $1} else print}' | cut -d '=' -f 2" #define ANDROID_FILE_PATH "/.local/share/applications/" #define ANDROID_APP_CURRENT "/.local/share/applications/." #define ANDROID_APP_UPER "/.local/share/applications/.." /** * @brief The ConvertDesktopToWinId class * 需要实现的功能,desktop文件与windowId的转换 * 需要暴露的dbus接口: * 传入desktop文件的路径,转化为(int)WindowId * 传入WindowId 转化为desktop文件路径 */ class ConvertDesktopToWinId: public QObject { Q_OBJECT public: ConvertDesktopToWinId(); ~ConvertDesktopToWinId(); //QList InfoPidList; QString m_desktopfilePath = nullptr; QString m_classClass = nullptr; QString m_className = nullptr; QString m_statusName = nullptr; QString m_cmdLine = nullptr; QDir *m_dir = nullptr; QDir *m_androidDir = nullptr; QFileInfoList m_list; QFileInfoList m_androidList; QString tranIdToDesktop(WId id); private: QString confirmDesktopFile(WId id); void searchFromEnviron(KWindowInfo info); void searchAndroidApp(KWindowInfo info); void searchTXeduApp(WId id); void compareClassName(); void compareCmdExec(); void compareLastStrategy(); void compareCmdName(); void compareDesktopClass(); void containsName(); QString getDesktopFileName(QString cmd); }; #endif // CONVERTDESKTOPTOWINID_H ukui-panel-3.0.6.4/panel-daemon/main.cpp0000644000175000017500000000160114203402514016335 0ustar fengfeng/* * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1, 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, see int main(int argc, char *argv[]) { QApplication a(argc, argv); WatcherManager manager; return a.exec(); }