⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 menutool.cc

📁 c++的guiQt做的开发
💻 CC
📖 第 1 页 / 共 3 页
字号:
/** @file This class manages Menu, Toolbars and Shortcuts Menus, menu items, toolbars and toolbar items share the same namespace and often menu and toolbar items are interchangable (only difference is that toolbar item must have icon, while menu item can be without an icon) @author Martin Petricek*/#include "menutool.h"#include "iconcache.h"#include "menuaction.h"#include "settings.h"#include "toolbar.h"#include "toolbutton.h"#include "util.h"#include <QByteArray>#include <QFile>#include <QLabel>#include <QMainWindow>#include <QMenu>#include <QMenuBar>#include <QPixmap>#include <QRegExp>#include <QString>#include <QTextStream>#include <assert.h>namespace gui {using namespace util;using namespace std;/** root key for system menu items */QString ROOT="gui/items/";/** root key for user menu items appended to system menu items (lists) */QString ROOT_ADD="gui/items_add/";/** Constructor of menu system for one specific window @param _main Main application window */MenuTool::MenuTool(QMainWindow *_main) { mainWindow=_main; cache=new IconCache();}/** Destructor */MenuTool::~MenuTool() { delete cache;}/** Throw exception with error message after encountering invalid menu/toolbar item @param type Type of offending item @param name Name of offending item @param line Line with offending item @param expected Optional "Expected" field hinting what is expected to make data valid*/void MenuTool::invalidItem(const QString &type,const QString &name,const QString &line,const QString &expected/*=QString::null*/) throw (InvalidMenuException) { QString err; err=QObject::tr("Invalid %1 in config:\nName: %2\nData: %3\n").arg(type,name,line); if (!expected.isNull()) err+="\n"+QObject::tr("Expected: ")+expected; throw InvalidMenuException(err);}/** Set root keys (prefixes) for items in configuration. Valid for all menus @param menuRoot root item for items @param menuRootAppend root item for extra items appended to lists*/void MenuTool::setRoots(const QString &menuRoot, const QString &menuRootAppend) { ROOT=menuRoot; ROOT_ADD=menuRootAppend;}/** Assigns action to given item @param item Item (toobar button or menu item) that caused the action @param action Name of action*/void MenuTool::setAction(void *item, const QString &action) { action_items_map[item]=action;}/** Return action string from given item @param item Item (toobar button or menu item) that caused the action @return Name of the specified action*/QString MenuTool::getAction(void *item) { return action_items_map[item];}/** Load one GUI item from config file, exiting application with fatal error if item not found @param name Name of the item to read @return line from config file */QString MenuTool::readItem(const QString &name) throw (InvalidMenuException) { QString line=globalSettings->read(ROOT+name); if (line.isNull()) throw InvalidMenuException(QObject::tr("Missing item in config")+":\n"+ROOT+name); line=line.trimmed(); if (line.length()==0) throw InvalidMenuException(QObject::tr("Missing item in config")+":\n"+ROOT+name); if (isList(line)) { //Read user-specified additional items and append them if this is a list  QString add=globalSettings->read(ROOT_ADD+name);  if (!add.isNull()) {   add=add.trimmed();   line+=",";   line+=add;  } } return line;}/** Check if menu item with given definition is a list @param line Definition of the item to check @return true if menu is a list */bool MenuTool::isList(const QString &line) { return (line.startsWith("list "));}/** Return popup menu with given name, loading if necessary @param name Name of the popup menu*/QMenu* MenuTool::createPopup(const QString &name) { if (popups[name]) return popups[name]; QMenu *m=new QMenu(); loadItems(name,m,QStringList()); popups[name]=m; return m;}/** Load all needed items into existing menu list @param line comma separated list of childs @param menu menu in which to load items (menu bar or popup menu) @param prev String list containing names of all parents of this menu item (used for loop detection)*/void MenuTool::loadItemsDef(QString line,QMenu *menu,QStringList prev/*=QStringList()*/) throw (InvalidMenuException) { QStringList qs=explode(MENULIST_SEPARATOR,line); QStringList::ConstIterator it=qs.begin(); for (;it!=qs.end();++it) { //load all subitems  loadItem(*it,menu,prev); } //All items loaded, now check items and their accelerators and maybe fill accels for items that don't have one optimizeItems(menu);}/** Load all needed items into existing menubar @param line comma separated list of childs @param menu menu in which to load items (menu bar or popup menu)*/void MenuTool::loadItemsDef(QString line,QMenuBar *menu) throw (InvalidMenuException) { QStringList qs=explode(MENULIST_SEPARATOR,line); QStringList::ConstIterator it=qs.begin(); for (;it!=qs.end();++it) { //load all subitems  loadItem(*it,menu); }}/** Add accelerator to items that do not have one @param menu Menu to process*/void MenuTool::optimizeItems(QMenu *menu) { assert(menu); QString used=mAccel[menu]; if (used.isNull()) used=""; QRegExp filter("[^a-z]",Qt::CaseInsensitive); QList<QAction*> mActs=menu->actions(); for (int i=0;i<mActs.count();i++) {  QAction *id=mActs.at(i);  //Get item text  QString itemCurrentText=id->text();  if (itemCurrentText.isNull()) continue;//Some separator or alike ...  if (getAccel(itemCurrentText)) continue; //This one already have accelerator  //Filter out all non-letter characters and get filterText  QString filterText=itemCurrentText;  filterText.replace(filter,"");  //Look for first usable letter  int idx=filterText.indexOf(QRegExp("[^"+used+"0]",Qt::CaseInsensitive));  if (idx<0) {   //No usable letter for accelerator found. How unfortunate ...   continue;  }  char pAccel=filterText[idx].toLower().toAscii();  //Find position of accel in original string  idx=itemCurrentText.indexOf(pAccel,0,Qt::CaseInsensitive);  assert(idx>=0);  //Add accel to string  itemCurrentText.insert(idx,'&');  //Update item  id->setText(itemCurrentText);  used+=pAccel; }}/** Parse name of list or item from line. List is then modified to contain only list of its items, or in case if item the rest of parameters @param line Line with menu list definition @param name Name (key) of this menu item (for locatization) @return localized caption of the menu item*/QString MenuTool::parseName(QString &line, const QString &name/*=QString::null*/) throw (InvalidMenuException) { QString caption; if (line.startsWith("item ")) {  line=line.remove(0,5);	//String "item "  caption=getUntil(MENUDEF_SEPARATOR,line,true); } else if (line.startsWith("list ")) {  line=line.remove(0,5);	//String "list "  caption=getUntil(MENULIST_SEPARATOR,line); } else {  invalidItem(QObject::tr("menu definition"),name,line); } QString menuName; if (name.isNull()) {  menuName=Settings::trUtf8(caption.toUtf8()); } else {  menuName=Settings::trUtf8(caption.toUtf8(),name.toUtf8()); } return menuName;}/** Load all needed items into existing menu list @param name name of item to be loaded from config file @param menu menu in which to load items (menu bar or popup menu) @param prev String list containing names of all parents of this menu item (used for loop detection)*/void MenuTool::loadItems(const QString &name,QMenu *menu,QStringList prev/*=QStringList()*/) throw (InvalidMenuException) { QString line=readItem(name); if (isList(line)) {  parseName(line,name);//Name ignored  loadItemsDef(line,menu,prev); } else { //We expect a list here  invalidItem(QObject::tr("menu definition"),name,line,QObject::tr("Menu items list")); }}/** Load all needed items into menubar @param name name of item to be loaded from config file @param menu menu in which to load items (menu bar or popup menu)*/void MenuTool::loadItems(const QString &name,QMenuBar *menu) throw (InvalidMenuException) { QString line=readItem(name); if (isList(line)) {  parseName(line,name);//Name ignored  loadItemsDef(line,menu); } else { //We expect a list here  invalidItem(QObject::tr("menu definition"),name,line,QObject::tr("Menu items list")); }}/** Load one menu item and insert it into parent menu. Recursively load subitems if item is a submenu. @param name name of item to be loaded from config file @param parent parent menubar @param parentMb parent menu item. @param prev String list containing names of all parents of this menu item (used for loop detection) If parent and parentMb are both NULL and the item is list, the item is loaded in cache, but not added anywhere */void MenuTool::loadItem(const QString &name,QMenu *parent/*=NULL*/,QMenuBar *parentMb/*=NULL*/,QStringList prev/*=QStringList()*/) throw (InvalidMenuException) { //Check for cycles (unhandled cycle in menu = crash in QT) if (prev.contains(name)) {  throw InvalidMenuException(QObject::tr("Cycle in menu detected")+":\n"+prev.join(" > ")+" > "+name); } prev+=name; //Separator requested - insert it and return if (name=="-" || name=="") {  if (parent) parent->addSeparator();  if (parentMb) parentMb->addSeparator();  return; } //Load items into list QString line=readItem(name); if (isList(line)) { // List of values - a submenu, first is name of submenu, others are items in it  QMenu *item;  QString menuName=parseName(line,name);  if (parent) {   item=parent->addMenu(menuName);   addToMap(name,parent,item->menuAction());  } else if (parentMb) {   item=parentMb->addMenu(menuName);   addToMap(name,NULL,item->menuAction());  } else {   /** \todo fix, adding to menubar/popup? ... */   item=new QMenu();  }  loadItemsDef(line,item,prev);  //Add this item to cache  /** \todo need multimap for always-correct behavior -> or warn in documentation about diff. behavior */  mCache[name]=item;  itemText.insert(name,menuName); } else if (line.startsWith("item ")) { // A single item  if (parent) addItem(line,parent,name); } else { //something invalid  invalidItem(QObject::tr("menu item"),name,line,"list | item"); }}/** Load one menu item and insert it into menubar. Recursively load subitems if item is a submenu. @param name name of item to be loaded from config file @param parent parent menubar */void MenuTool::loadItem(const QString &name,QMenuBar *parent) throw (InvalidMenuException) { loadItem(name,NULL,parent);}/** Load one menu item and insert it into parent menu. Recursively load subitems if item is a submenu. @param name name of item to be loaded from config file @param parent parent menu item. If NULL and the item is list, the item is loaded in cache, but not added anywhere @param prev String list containing names of all parents of this menu item (used for loop detection) */void MenuTool::loadItem(const QString &name,QMenu *parent/*=NULL*/,QStringList prev/*=QStringList()*/) throw (InvalidMenuException) { loadItem(name,parent,NULL,prev);}/** Get accelerator for given description @param name Name of menu item @return accelerator (the character after '&') */char MenuTool::getAccel(const QString &name) { int pos=name.indexOf('&'); if (pos==-1) return 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -