From de18d919e7c940b402a6e213f7deb21e2f187e22 Mon Sep 17 00:00:00 2001 From: Michael Pfeiffer Date: Sat, 30 Oct 2010 06:54:16 +0000 Subject: [PATCH] * Added driver specific settings to job data and job setup dialog. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@39191 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/libs/print/libprint/JobData.h | 12 +++ headers/libs/print/libprint/JobSetupDlg.h | 23 +++-- headers/libs/print/libprint/PrinterCap.h | 66 +++++++++++++- src/libs/print/libprint/JobData.cpp | 88 +++++++++++++++++- src/libs/print/libprint/JobSetupDlg.cpp | 105 ++++++++++++++++++++-- src/libs/print/libprint/PrinterCap.cpp | 58 ++++++++---- 6 files changed, 315 insertions(+), 37 deletions(-) diff --git a/headers/libs/print/libprint/JobData.h b/headers/libs/print/libprint/JobData.h index 97475ccab6..aa68dfa032 100644 --- a/headers/libs/print/libprint/JobData.h +++ b/headers/libs/print/libprint/JobData.h @@ -10,6 +10,9 @@ #include #include +#include +#include + #include "Halftone.h" #include "MarginView.h" // for MarginUnit @@ -255,6 +258,7 @@ private: Halftone::DitherType fDitherType; PageSelection fPageSelection; MarginUnit fMarginUnit; + map fDriverSpecificSettings; public: JobData(BMessage *msg, const PrinterCap *cap, Settings settings); @@ -355,6 +359,14 @@ public: MarginUnit getMarginUnit() const { return fMarginUnit; } void setMarginUnit(MarginUnit marginUnit) { fMarginUnit = marginUnit; } + + bool HasDriverSpecificSetting(const string& category) const; + const string& DriverSpecificSetting(const string& category) const; + void SetDriverSpecificSetting(const string& category, const string& value); + +private: + void SerializePrinterSpecificSettings(BString& serializedSettings); + void DeserializePrinterSpecificSettings(BString& serializedSettings); }; #endif /* __JOBDATA_H */ diff --git a/headers/libs/print/libprint/JobSetupDlg.h b/headers/libs/print/libprint/JobSetupDlg.h index 3d1e414f7c..f848afc7c8 100644 --- a/headers/libs/print/libprint/JobSetupDlg.h +++ b/headers/libs/print/libprint/JobSetupDlg.h @@ -7,6 +7,8 @@ #define __JOBSETUPDLG_H #include +#include + #include "DialogWindow.h" #include "JobData.h" @@ -14,16 +16,17 @@ #include "JSDSlider.h" #include "PrinterCap.h" +class BCheckBox; +class BGridLayout; +class BPopUpMenu; +class BRadioButton; class BTextControl; class BTextView; -class BRadioButton; -class BCheckBox; -class BPopUpMenu; -class JobData; -class PrinterData; -class PrinterCap; class HalftoneView; +class JobData; class PagesView; +class PrinterCap; +class PrinterData; class JobSetupView : public BView { public: @@ -37,6 +40,13 @@ private: void UpdateButtonEnabledState(); bool IsHalftoneConfigurationNeeded(); void CreateHalftoneConfigurationUI(); + void AddDriverSpecificSettings(BGridLayout* gridLayout, int row); + string GetDriverSpecificValue(PrinterCap::CapID category, + const char* key); + template + void FillCapabilityMenu(BPopUpMenu* menu, uint32 message, + const BaseCap** capabilities, int count, + Predicate& predicate); void FillCapabilityMenu(BPopUpMenu* menu, uint32 message, PrinterCap::CapID category, int id); void FillCapabilityMenu(BPopUpMenu* menu, uint32 message, @@ -78,6 +88,7 @@ private: BRadioButton* fAllPages; BRadioButton* fOddNumberedPages; BRadioButton* fEvenNumberedPages; + std::map fDriverSpecificLists; }; class JobSetupDlg : public DialogWindow { diff --git a/headers/libs/print/libprint/PrinterCap.h b/headers/libs/print/libprint/PrinterCap.h index 4cec731012..004e523d99 100644 --- a/headers/libs/print/libprint/PrinterCap.h +++ b/headers/libs/print/libprint/PrinterCap.h @@ -117,7 +117,7 @@ struct DriverSpecificCap : public BaseCap { }; DriverSpecificCap(const string& label, - bool isDefault, int32 category, Type type); + int32 category, Type type); int32 ID() const; @@ -125,6 +125,13 @@ struct DriverSpecificCap : public BaseCap { Type fType; }; +struct ListItemCap : public BaseCap { + ListItemCap(const string& label, + bool isDefault, int32 id); + + int32 ID() const; + int32 fID; +}; class PrinterData; @@ -142,7 +149,7 @@ public: kBindingLocation, kColor, kProtocolClass, - kDriverSpecifcCapababilities, + kDriverSpecificCapabilities, // Static boolean settings follow. // For them isSupport() has to be implemented only. @@ -151,7 +158,54 @@ public: // for class Halftone? // The driver specific generic capabilities start here - kDriverSpecificCapabablitiesBegin = 100 + kDriverSpecificCapabilitiesBegin = 100 + }; + + struct IDPredicate + { + IDPredicate(int id) + : fID(id) + { + } + + + bool operator()(const BaseCap* baseCap) { + return baseCap->ID() == fID; + } + + int fID; + }; + + struct LabelPredicate + { + LabelPredicate(const char* label) + : fLabel(label) + { + } + + + bool operator()(const BaseCap* baseCap) { + return baseCap->fLabel == fLabel; + } + + const char* fLabel; + + }; + + struct KeyPredicate + { + KeyPredicate(const char* key) + : fKey(key) + { + } + + + bool operator()(const BaseCap* baseCap) { + return baseCap->fKey == fKey; + } + + const char* fKey; + }; virtual int countCap(CapID category) const = 0; @@ -160,12 +214,16 @@ public: const BaseCap* getDefaultCap(CapID category) const; const BaseCap* findCap(CapID category, int id) const; const BaseCap* findCap(CapID category, const char* label) const; + const BaseCap* findCapWithKey(CapID category, const char* key) + const; int getProtocolClass() const; protected: PrinterCap(const PrinterCap& printerCap); PrinterCap& operator=(const PrinterCap& printerCap); + template + const BaseCap* findCap(CapID category, Predicate& predicate) const; const PrinterData* getPrinterData() const; @@ -174,4 +232,6 @@ private: }; + + #endif /* __PRINTERCAP_H */ diff --git a/src/libs/print/libprint/JobData.cpp b/src/libs/print/libprint/JobData.cpp index 3c00c4287f..36bdf83088 100644 --- a/src/libs/print/libprint/JobData.cpp +++ b/src/libs/print/libprint/JobData.cpp @@ -3,9 +3,13 @@ * Copyright 1999-2000 Y.Takagi. All Rights Reserved. */ +#include "JobData.h" + #include #include -#include "JobData.h" + +#include + #include "PrinterCap.h" #include "DbgMsg.h" @@ -39,6 +43,9 @@ static const char* kJDMarginUnit = "JJJJ_margin_unit"; static const char* kJDPhysicalRect = "JJJJ_physical_rect"; static const char* kJDScaledPhysicalRect = "JJJJ_scaled_physical_rect"; static const char* kJDResolution = "JJJJ_resolution"; +static const char* kJDDriverSpecificSettings = "JJJJ_driverSpecificSettings"; + +static const char* kDriverSpecificSettingsSeparator = ";"; JobData::JobData(BMessage *msg, const PrinterCap *cap, Settings settings) @@ -92,6 +99,7 @@ JobData::operator=(const JobData &job_data) fMarginUnit = job_data.fMarginUnit; fPhysicalRect = job_data.fPhysicalRect; fScaledPhysicalRect = job_data.fScaledPhysicalRect; + fDriverSpecificSettings = job_data.fDriverSpecificSettings; return *this; } @@ -288,6 +296,11 @@ JobData::load(BMessage *msg, const PrinterCap *cap, Settings settings) fMarginUnit = (MarginUnit)msg->FindInt32(kJDMarginUnit); else fMarginUnit = kUnitInch; + + BString serializedSettings; + if (msg->HasString(kJDDriverSpecificSettings)) + msg->FindString(kJDDriverSpecificSettings, &serializedSettings); + DeserializePrinterSpecificSettings(serializedSettings); } @@ -406,4 +419,77 @@ JobData::save(BMessage *msg) msg->RemoveName(kJDPageSelection); if (fSettings == kJobSettings) msg->AddInt32(kJDPageSelection, fPageSelection); + + msg->RemoveName(kJDDriverSpecificSettings); + if (fSettings == kJobSettings) + { + BString serializedSettings; + SerializePrinterSpecificSettings(serializedSettings); + msg->AddString(kJDDriverSpecificSettings, serializedSettings); + } +} + + +bool +JobData::HasDriverSpecificSetting(const string& category) const +{ + return fDriverSpecificSettings.find(category) != + fDriverSpecificSettings.end(); +} + + +const string& +JobData::DriverSpecificSetting(const string& category) const +{ + return fDriverSpecificSettings.find(category)->second; +} + + +void +JobData::SetDriverSpecificSetting(const string& category, const string& value) +{ + fDriverSpecificSettings[category] = value; +} + + +void +JobData::SerializePrinterSpecificSettings(BString& serializedSettings) +{ + bool first = true; + map::iterator it = fDriverSpecificSettings.begin(); + for (; it != fDriverSpecificSettings.end(); it++) { + if (first) + first = false; + else + serializedSettings << kDriverSpecificSettingsSeparator; + + serializedSettings << it->first.c_str() + << kDriverSpecificSettingsSeparator + << it->second.c_str(); + } +} + + +void +JobData::DeserializePrinterSpecificSettings(BString& serializedSettings) +{ + // Note: strtok_r terminates the string after the first token + fDriverSpecificSettings.clear(); + + int length = serializedSettings.Length() + 1; + char* state = NULL; + char* buffer = serializedSettings.LockBuffer(length); + const char* separator = kDriverSpecificSettingsSeparator; + char* token = strtok_r(buffer, separator, &state); + while (token != NULL) { + char* key = token; + token = strtok_r(NULL, separator, &state); + if (token == NULL) + break; + char* value = token; + fDriverSpecificSettings[key] = value; + token = strtok_r(NULL, separator, &state); + } + + serializedSettings.UnlockBuffer(0); } diff --git a/src/libs/print/libprint/JobSetupDlg.cpp b/src/libs/print/libprint/JobSetupDlg.cpp index c33ec48c41..827dd9da61 100644 --- a/src/libs/print/libprint/JobSetupDlg.cpp +++ b/src/libs/print/libprint/JobSetupDlg.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -257,7 +258,7 @@ JobSetupView::AttachedToWindow() fNup = new BPopUpMenu(""); fNup->SetRadioMode(true); FillCapabilityMenu(fNup, kMsgNone, gNups, sizeof(gNups) / sizeof(gNups[0]), - fJobData->getNup()); + (int)fJobData->getNup()); BMenuField* pagesPerSheet = new BMenuField("pagesPerSheet", "Pages Per Sheet:", fNup); @@ -348,6 +349,8 @@ JobSetupView::AttachedToWindow() qualityGridLayout->AddView(fGamma, 0, 2, 2); qualityGridLayout->AddView(fInkDensity, 0, 3, 2); qualityGridLayout->AddView(fHalftoneBox, 0, 4, 2); + } else { + AddDriverSpecificSettings(qualityGridLayout, 1); } qualityGridLayout->SetSpacing(0, 0); qualityGridLayout->SetInsets(5, 5, 5, 5); @@ -447,7 +450,7 @@ JobSetupView::CreateHalftoneConfigurationUI() fDitherType->SetRadioMode(true); FillCapabilityMenu(fDitherType, kMsgQuality, gDitherTypes, sizeof(gDitherTypes) / sizeof(gDitherTypes[0]), - fJobData->getDitherType()); + (int)fJobData->getDitherType()); fDitherMenuField = new BMenuField("dithering", "Dot Pattern:", fDitherType); fDitherType->SetTargetForItems(this); @@ -489,17 +492,69 @@ JobSetupView::CreateHalftoneConfigurationUI() void -JobSetupView::FillCapabilityMenu(BPopUpMenu* menu, uint32 message, - PrinterCap::CapID category, int id) +JobSetupView::AddDriverSpecificSettings(BGridLayout* gridLayout, int row) { - int count = fPrinterCap->countCap(category); - const BaseCap **capabilities = fPrinterCap->enumCap(category); - FillCapabilityMenu(menu, message, capabilities, count, id); + if (!fPrinterCap->isSupport(PrinterCap::kDriverSpecificCapabilities)) + return; + + int count = fPrinterCap->countCap(PrinterCap::kDriverSpecificCapabilities); + const BaseCap** capabilities = fPrinterCap->enumCap( + PrinterCap::kDriverSpecificCapabilities); + + for (int i = 0; i < count; i ++) { + const DriverSpecificCap* capability = static_cast( + capabilities[i]); + + const char* label = capability->fLabel.c_str(); + BPopUpMenu* popUpMenu = new BPopUpMenu(label); + popUpMenu->SetRadioMode(true); + + PrinterCap::CapID category = static_cast( + capability->ID()); + + const BaseCap** categoryCapabilities = fPrinterCap->enumCap(category); + + int categoryCount = fPrinterCap->countCap(category); + + string value = GetDriverSpecificValue(category, capability->Key()); + PrinterCap::KeyPredicate predicate(value.c_str()); + + FillCapabilityMenu(popUpMenu, kMsgNone, categoryCapabilities, + categoryCount, predicate); + + BString menuLabel = label; + menuLabel << ":"; + BMenuField* menuField = new BMenuField(label, menuLabel.String(), + popUpMenu); + popUpMenu->SetTargetForItems(this); + + gridLayout->AddItem(menuField->CreateLabelLayoutItem(), + 0, row); + gridLayout->AddItem(menuField->CreateMenuBarLayoutItem(), + 1, row); + row ++; + + fDriverSpecificLists[category] = popUpMenu; + } } + +string +JobSetupView::GetDriverSpecificValue(PrinterCap::CapID category, + const char* key) +{ + if (fJobData->HasDriverSpecificSetting(key)) + return fJobData->DriverSpecificSetting(key); + + const BaseCap* defaultCapability = fPrinterCap->getDefaultCap(category); + return defaultCapability->fKey; +} + + +template void JobSetupView::FillCapabilityMenu(BPopUpMenu* menu, uint32 message, - const BaseCap** capabilities, int count, int id) + const BaseCap** capabilities, int count, Predicate& predicate) { bool marked = false; @@ -523,7 +578,7 @@ JobSetupView::FillCapabilityMenu(BPopUpMenu* menu, uint32 message, defaultItem = item; - if (capability->ID() == id) { + if (predicate(capability)) { item->SetMarked(true); marked = true; } @@ -541,6 +596,26 @@ JobSetupView::FillCapabilityMenu(BPopUpMenu* menu, uint32 message, } +void +JobSetupView::FillCapabilityMenu(BPopUpMenu* menu, uint32 message, + PrinterCap::CapID category, int id) +{ + PrinterCap::IDPredicate predicate(id); + int count = fPrinterCap->countCap(category); + const BaseCap **capabilities = fPrinterCap->enumCap(category); + FillCapabilityMenu(menu, message, capabilities, count, predicate); +} + + +void +JobSetupView::FillCapabilityMenu(BPopUpMenu* menu, uint32 message, + const BaseCap** capabilities, int count, int id) +{ + PrinterCap::IDPredicate predicate(id); + FillCapabilityMenu(menu, message, capabilities, count, predicate); +} + + int JobSetupView::GetID(const BaseCap** capabilities, int count, const char* label, int defaultValue) @@ -703,6 +778,18 @@ JobSetupView::UpdateJobData(bool showPreview) pageSelection = JobData::kEvenNumberedPages; fJobData->setPageSelection(pageSelection); + std::map::iterator it = + fDriverSpecificLists.begin(); + for(; it != fDriverSpecificLists.end(); it++) { + PrinterCap::CapID category = it->first; + BPopUpMenu* popUpMenu = it->second; + const char* key = fPrinterCap->findCap( + PrinterCap::kDriverSpecificCapabilities, (int)category)->Key(); + const char* label = popUpMenu->FindMarked()->Label(); + const char* value = fPrinterCap->findCap(category, label)->Key(); + fJobData->SetDriverSpecificSetting(key, value); + } + fJobData->save(); return true; } diff --git a/src/libs/print/libprint/PrinterCap.cpp b/src/libs/print/libprint/PrinterCap.cpp index ce3826b0bb..ca35cef653 100644 --- a/src/libs/print/libprint/PrinterCap.cpp +++ b/src/libs/print/libprint/PrinterCap.cpp @@ -158,10 +158,10 @@ ProtocolClassCap::ID() const } -DriverSpecificCap::DriverSpecificCap(const string& label, bool isDefault, - int32 category, Type type) +DriverSpecificCap::DriverSpecificCap(const string& label, int32 category, + Type type) : - BaseCap(label, isDefault), + BaseCap(label, false), fCategory(category), fType(type) { @@ -175,6 +175,21 @@ DriverSpecificCap::ID() const } +ListItemCap::ListItemCap(const string& label, bool isDefault, int32 id) + : + BaseCap(label, isDefault), + fID(id) +{ +} + + +int32 +ListItemCap::ID() const +{ + return fID; +} + + PrinterCap::PrinterCap(const PrinterData *printer_data) : fPrinterData(printer_data) @@ -206,8 +221,9 @@ PrinterCap::getDefaultCap(CapID category) const } +template const BaseCap* -PrinterCap::findCap(CapID category, int id) const +PrinterCap::findCap(CapID category, Predicate& predicate) const { int count = countCap(category); if (count <= 0) @@ -215,33 +231,39 @@ PrinterCap::findCap(CapID category, int id) const const BaseCap **base_cap = enumCap(category); while (count--) { - if ((*base_cap)->ID() == id) { + if (predicate(*base_cap)) { return *base_cap; } base_cap++; } return NULL; + +} + +const BaseCap* +PrinterCap::findCap(CapID category, int id) const +{ + IDPredicate predicate(id); + return findCap(category, predicate); } const BaseCap* PrinterCap::findCap(CapID category, const char* label) const { - int count = countCap(category); - if (count <= 0) - return NULL; - - const BaseCap **base_cap = enumCap(category); - while (count--) { - if ((*base_cap)->fLabel == label) { - return *base_cap; - } - base_cap++; - } - return NULL; - + LabelPredicate predicate(label); + return findCap(category, predicate); } + +const BaseCap* +PrinterCap::findCapWithKey(CapID category, const char* key) const +{ + KeyPredicate predicate(key); + return findCap(category, predicate); +} + + int PrinterCap::getProtocolClass() const { return fPrinterData->getProtocolClass();